123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- #include "gpsd_config.h"
- #include <stdio.h>
- #include <stdbool.h>
- #include <string.h>
- #include <math.h>
- #include <unistd.h>
- #include "gpsd.h"
- #include "bits.h"
- #include "strfuncs.h"
- #define get16z(buf, n) ( (buf[2*(n)-2]) \
- | (buf[2*(n)-1] << 8))
- #define get32z(buf, n) ( (buf[2*(n)-2]) \
- | (buf[2*(n)-1] << 8) \
- | (buf[2*(n)+0] << 16) \
- | (buf[2*(n)+1] << 24))
- #define getstringz(to, from, s, e) \
- (void)memcpy(to, from+2*(s)-2, 2*((e)-(s)+1))
- #ifdef ZODIAC_ENABLE
- struct header
- {
- unsigned short sync;
- unsigned short id;
- unsigned short ndata;
- unsigned short flags;
- unsigned short csum;
- };
- static unsigned short zodiac_checksum(unsigned short *w, int n)
- {
- unsigned short csum = 0;
- while (n-- > 0)
- csum += *(w++);
- return -csum;
- }
- static ssize_t end_write(int fd, void *d, size_t len)
- {
- unsigned char buf[BUFSIZ];
- short *data = (short *)d;
- size_t n;
- for (n = 0; n < (size_t)(len/2); n++)
- putle16(buf, n*2, data[n]);
- return write(fd, (char*)buf, len);
- }
- static ssize_t zodiac_spew(struct gps_device_t *session, unsigned short type,
- unsigned short *dat, int dlen)
- {
- struct header h;
- int i;
- char buf[BUFSIZ];
- h.sync = 0x81ff;
- h.id = (unsigned short)type;
- h.ndata = (unsigned short)(dlen - 1);
- h.flags = 0;
- h.csum = zodiac_checksum((unsigned short *)&h, 4);
- if (!BAD_SOCKET(session->gpsdata.gps_fd)) {
- size_t hlen, datlen;
- hlen = sizeof(h);
- datlen = sizeof(unsigned short) * dlen;
- if (end_write(session->gpsdata.gps_fd, &h, hlen) != (ssize_t) hlen ||
- end_write(session->gpsdata.gps_fd, dat,
- datlen) != (ssize_t) datlen) {
- GPSD_LOG(LOG_INFO, &session->context->errout,
- "Reconfigure write failed\n");
- return -1;
- }
- }
- (void)snprintf(buf, sizeof(buf),
- "%04x %04x %04x %04x %04x",
- h.sync, h.id, h.ndata, h.flags, h.csum);
- for (i = 0; i < dlen; i++)
- str_appendf(buf, sizeof(buf), " %04x", dat[i]);
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Sent Zodiac packet: %s\n", buf);
- return 0;
- }
- static void send_rtcm(struct gps_device_t *session,
- const char *rtcmbuf, size_t rtcmbytes)
- {
- unsigned short data[34];
- int n = 1 + (int)(rtcmbytes / 2 + rtcmbytes % 2);
- if (session->driver.zodiac.sn++ > 32767)
- session->driver.zodiac.sn = 0;
- memset(data, 0, sizeof(data));
- data[0] = session->driver.zodiac.sn;
- memcpy(&data[1], rtcmbuf, rtcmbytes);
- data[n] = zodiac_checksum(data, n);
- (void)zodiac_spew(session, 1351, data, n + 1);
- }
- static ssize_t zodiac_send_rtcm(struct gps_device_t *session,
- const char *rtcmbuf, size_t rtcmbytes)
- {
- while (rtcmbytes > 0) {
- size_t len = (size_t) (rtcmbytes > 64 ? 64 : rtcmbytes);
- send_rtcm(session, rtcmbuf, len);
- rtcmbytes -= len;
- rtcmbuf += len;
- }
- return 1;
- }
- #define getzword(n) get16z(session->lexer.outbuffer, n)
- #define getzlong(n) get32z(session->lexer.outbuffer, n)
- static gps_mask_t handle1000(struct gps_device_t *session)
- {
- gps_mask_t mask;
- struct tm unpacked_date;
- int datum;
- char ts_buf[TIMESPEC_LEN];
-
-
-
- session->gpsdata.status = (getzword(10) & 0x1c) ? 0 : 1;
- if (session->gpsdata.status != 0)
- session->newdata.mode = (getzword(10) & 1) ? MODE_2D : MODE_3D;
- else
- session->newdata.mode = MODE_NO_FIX;
-
- session->gpsdata.satellites_used = (int)getzword(12);
-
- session->context->gps_week = (unsigned short)getzword(14);
-
-
- unpacked_date.tm_mday = (int)getzword(19);
- unpacked_date.tm_mon = (int)getzword(20) - 1;
- unpacked_date.tm_year = (int)getzword(21) - 1900;
- unpacked_date.tm_hour = (int)getzword(22);
- unpacked_date.tm_min = (int)getzword(23);
- unpacked_date.tm_sec = (int)getzword(24);
- unpacked_date.tm_isdst = 0;
- session->newdata.time.tv_sec = mkgmtime(&unpacked_date);
- session->newdata.time.tv_nsec = getzlong(25);
- session->newdata.latitude = ((long)getzlong(27)) * RAD_2_DEG * 1e-8;
- session->newdata.longitude = ((long)getzlong(29)) * RAD_2_DEG * 1e-8;
-
- session->newdata.altHAE = ((long)getzlong(31)) * 1e-2;
- session->newdata.geoid_sep = ((short)getzword(33)) * 1e-2;
- session->newdata.speed = (int)getzlong(34) * 1e-2;
- session->newdata.track = (int)getzword(36) * RAD_2_DEG * 1e-3;
- session->newdata.magnetic_var = ((short)getzword(37)) * RAD_2_DEG * 1e-4;
- session->newdata.climb = ((short)getzword(38)) * 1e-2;
- datum = getzword(39);
- datum_code_string(datum, session->newdata.datum,
- sizeof(session->newdata.datum));
-
- session->newdata.eph = (int)getzlong(40) * 1e-2 * GPSD_CONFIDENCE;
- session->newdata.epv = (int)getzlong(42) * 1e-2 * GPSD_CONFIDENCE;
- session->newdata.ept = (int)getzlong(44) * 1e-2 * GPSD_CONFIDENCE;
- session->newdata.eps = (int)getzword(46) * 1e-2 * GPSD_CONFIDENCE;
-
-
-
-
- mask = TIME_SET | NTPTIME_IS | LATLON_SET | ALTITUDE_SET | CLIMB_SET |
- SPEED_SET | TRACK_SET | STATUS_SET | MODE_SET |
- HERR_SET | SPEEDERR_SET | VERR_SET;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "1000: time=%s lat=%.2f lon=%.2f altHAE=%.2f track=%.2f "
- "speed=%.2f climb=%.2f mode=%d status=%d\n",
- timespec_str(&session->newdata.time, ts_buf, sizeof(ts_buf)),
- session->newdata.latitude,
- session->newdata.longitude, session->newdata.altHAE,
- session->newdata.track, session->newdata.speed,
- session->newdata.climb, session->newdata.mode,
- session->gpsdata.status);
- return mask;
- }
- static gps_mask_t handle1002(struct gps_device_t *session)
- {
- int i;
- timespec_t ts_tow;
-
-
-
- int gps_week = getzword(10);
- time_t gps_seconds = getzlong(11);
- long gps_nanoseconds = getzlong(13);
- char ts_buf[TIMESPEC_LEN];
-
- session->context->gps_week = (unsigned short)gps_week;
- session->gpsdata.satellites_used = 0;
- for (i = 0; i < ZODIAC_CHANNELS; i++) {
- int status, prn;
- session->driver.zodiac.Zv[i] = status = (int)getzword(15 + (3 * i));
- session->driver.zodiac.Zs[i] = prn = (int)getzword(16 + (3 * i));
- if (status & 1)
- session->gpsdata.satellites_used++;
- session->gpsdata.skyview[i].PRN = (short)prn;
- session->gpsdata.skyview[i].ss = (float)getzword(17 + (3 * i));
- session->gpsdata.skyview[i].used = (bool)(status & 1);
- }
- ts_tow.tv_sec = gps_seconds;
- ts_tow.tv_nsec = gps_nanoseconds;
- session->gpsdata.skyview_time = gpsd_gpstime_resolv(session,
- (unsigned short)gps_week,
- ts_tow);
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "1002: visible=%d used=%d mask={SATELLITE|USED} time %s\n",
- session->gpsdata.satellites_visible,
- session->gpsdata.satellites_used,
- timespec_str(&session->gpsdata.skyview_time, ts_buf,
- sizeof(ts_buf)));
- return SATELLITE_SET | USED_IS;
- }
- static gps_mask_t handle1003(struct gps_device_t *session)
- {
- int i, n;
-
- n = (int)getzword(14);
- if ((n < 0) || (n > 12))
- return 0;
- gpsd_zero_satellites(&session->gpsdata);
-
-
- session->gpsdata.dop.gdop = (unsigned int)getzword(9) * 1e-2;
- session->gpsdata.dop.pdop = (unsigned int)getzword(10) * 1e-2;
- session->gpsdata.dop.hdop = (unsigned int)getzword(11) * 1e-2;
- session->gpsdata.dop.vdop = (unsigned int)getzword(12) * 1e-2;
- session->gpsdata.dop.tdop = (unsigned int)getzword(13) * 1e-2;
- session->gpsdata.satellites_visible = n;
- for (i = 0; i < ZODIAC_CHANNELS; i++) {
- if (i < session->gpsdata.satellites_visible) {
- session->gpsdata.skyview[i].PRN = (short)getzword(15 + (3 * i));
- session->gpsdata.skyview[i].azimuth =
- (((double)getzword(16 + (3 * i))) * RAD_2_DEG * 1e-4);
- if (session->gpsdata.skyview[i].azimuth < 0)
- session->gpsdata.skyview[i].azimuth += 360;
- session->gpsdata.skyview[i].elevation =
- (((double)getzword(17 + (3 * i))) * RAD_2_DEG * 1e-4);
- } else {
- session->gpsdata.skyview[i].PRN = 0;
- session->gpsdata.skyview[i].azimuth = NAN;
- session->gpsdata.skyview[i].elevation = NAN;
- session->gpsdata.skyview[i].ss = NAN;
- }
- }
- session->gpsdata.skyview_time.tv_sec = 0;
- session->gpsdata.skyview_time.tv_nsec = 0;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "NAVDOP: visible=%d gdop=%.2f pdop=%.2f "
- "hdop=%.2f vdop=%.2f tdop=%.2f mask={SATELLITE|DOP}\n",
- session->gpsdata.satellites_visible,
- session->gpsdata.dop.gdop,
- session->gpsdata.dop.hdop,
- session->gpsdata.dop.vdop,
- session->gpsdata.dop.pdop, session->gpsdata.dop.tdop);
- return SATELLITE_SET | DOP_SET;
- }
- static void handle1005(struct gps_device_t *session UNUSED)
- {
-
-
- int numcorrections = (int)getzword(12);
- if (session->newdata.mode == MODE_NO_FIX)
- session->gpsdata.status = STATUS_NO_FIX;
- else if (numcorrections == 0)
- session->gpsdata.status = STATUS_FIX;
- else
- session->gpsdata.status = STATUS_DGPS_FIX;
- }
- static gps_mask_t handle1011(struct gps_device_t *session)
- {
-
- getstringz(session->subtype, session->lexer.outbuffer, 19, 28);
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "1011: subtype=%s mask={DEVICEID}\n",
- session->subtype);
- return DEVICEID_SET;
- }
- static void handle1108(struct gps_device_t *session)
- {
-
-
-
-
- if ((int)(getzword(19) & 3) == 3) {
- session->context->valid |= LEAP_SECOND_VALID;
- session->context->leap_seconds = (int)getzword(16);
- }
- }
- static gps_mask_t zodiac_analyze(struct gps_device_t *session)
- {
- unsigned int id =
- (unsigned int)((session->lexer.outbuffer[3] << 8) |
- session->lexer.outbuffer[2]);
-
- if (session->context->errout.debug >= LOG_RAW)
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Raw Zodiac packet type %d length %zd: %s\n",
- id, session->lexer.outbuflen, gpsd_prettydump(session));
- if (session->lexer.outbuflen < 10)
- return 0;
-
- session->cycle_end_reliable = true;
- switch (id) {
- case 1000:
- return handle1000(session) | (CLEAR_IS | REPORT_IS);
- case 1002:
- return handle1002(session);
- case 1003:
- return handle1003(session);
- case 1005:
- handle1005(session);
- return 0;
- case 1011:
- return handle1011(session);
- case 1108:
- handle1108(session);
- return 0;
- default:
- return 0;
- }
- }
- #ifdef CONTROLSEND_ENABLE
- static ssize_t zodiac_control_send(struct gps_device_t *session,
- char *msg, size_t len)
- {
- unsigned short shortwords[256];
- #define min(x,y) ((x) < (y) ? x : y)
- /*
- * We used to just cast msg to an unsigned short pointer.
- * This can fail on word-oriented achitectures like a SPARC.
- */
- memcpy((char *)shortwords, msg, min(sizeof(shortwords), len));
- /* and if len isn't even, it's your own fault */
- return zodiac_spew(session, shortwords[0], shortwords + 1,
- (int)(len / 2 - 1));
- }
- #endif /* CONTROLSEND_ENABLE */
- #ifdef RECONFIGURE_ENABLE
- static bool zodiac_speed_switch(struct gps_device_t *session,
- speed_t speed, char parity, int stopbits)
- {
- unsigned short data[15];
- if (session->driver.zodiac.sn++ > 32767)
- session->driver.zodiac.sn = 0;
- switch (parity) {
- case 'E':
- case 2:
- parity = (char)2;
- break;
- case 'O':
- case 1:
- parity = (char)1;
- break;
- case 'N':
- case 0:
- default:
- parity = (char)0;
- break;
- }
- memset(data, 0, sizeof(data));
-
- data[0] = session->driver.zodiac.sn;
- data[1] = 1;
- data[2] = (unsigned short)parity;
- data[3] = (unsigned short)(stopbits - 1);
- data[4] = 0;
- data[5] = (unsigned short)(round(log((double)speed / 300) / GPS_LN2) + 1);
- data[14] = zodiac_checksum(data, 14);
- (void)zodiac_spew(session, 1330, data, 15);
- return true;
- }
- #endif
- static double zodiac_time_offset(struct gps_device_t *session UNUSED)
- {
-
- return 1.1;
- }
- const struct gps_type_t driver_zodiac =
- {
- .type_name = "Zodiac",
- .packet_type = ZODIAC_PACKET,
- .flags = DRIVER_STICKY,
- .trigger = NULL,
- .channels = 12,
- .probe_detect = NULL,
- .get_packet = generic_get,
- .parse_packet = zodiac_analyze,
- .rtcm_writer = zodiac_send_rtcm,
- .init_query = NULL,
- .event_hook = NULL,
- #ifdef RECONFIGURE_ENABLE
- .speed_switcher = zodiac_speed_switch,
- .mode_switcher = NULL,
- .rate_switcher = NULL,
- .min_cycle.tv_sec = 1,
- .min_cycle.tv_nsec = 0,
- #endif
- #ifdef CONTROLSEND_ENABLE
- .control_send = zodiac_control_send,
- #endif
- .time_offset = zodiac_time_offset,
- };
- #endif
|