1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291 |
- #include "gpsd_config.h"
- #include <errno.h>
- #include <math.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #if defined(HAVE_LIBUSB)
- #include <libusb.h>
- #endif
- #include "gpsd.h"
- #include "bits.h"
- #include "timespec.h"
- #define GPSD_LE16TOH(x) getles16((char *)(&(x)), 0)
- #define GPSD_LE32TOH(x) getles32((char *)(&(x)), 0)
- #ifdef GARMIN_ENABLE
- #define USE_RMD 0
- #define ETX 0x03
- #define ACK 0x06
- #define DLE 0x10
- #define NAK 0x15
- #define GARMIN_LAYERID_TRANSPORT (uint8_t) 0
- #define GARMIN_LAYERID_APPL (uint32_t) 20
- #define GARMIN_LAYERID_PRIVATE 0x01106E4B
- #define PRIV_PKTID_SET_DEBUG 1
- #define PRIV_PKTID_SET_MODE 2
- #define PRIV_PKTID_INFO_REQ 3
- #define PRIV_PKTID_INFO_RESP 4
- #define PRIV_PKTID_RESET_REQ 5
- #define PRIV_PKTID_SET_DEF_MODE 6
- #define MODE_NATIVE 0
- #define MODE_GARMIN_SERIAL 1
- #define GARMIN_PKTID_TRANSPORT_START_SESSION_REQ 5
- #define GARMIN_PKTID_TRANSPORT_START_SESSION_RESP 6
- #define GARMIN_PKTID_PROTOCOL_ARRAY 253
- #define GARMIN_PKTID_PRODUCT_RQST 254
- #define GARMIN_PKTID_PRODUCT_DATA 255
- #define GARMIN_PKTID_RMD41_DATA 41
- #define GARMIN_PKTID_PVT_DATA 51
- #define GARMIN_PKTID_RMD_DATA 52
- #define GARMIN_PKTID_SAT_DATA 114
- #define GARMIN_PKTID_L001_XFER_CMPLT 12
- #define GARMIN_PKTID_L001_COMMAND_DATA 10
- #define GARMIN_PKTID_L001_DATE_TIME_DATA 14
- #define GARMIN_PKTID_L001_RECORDS 27
- #define GARMIN_PKTID_L001_WPT_DATA 35
- #define CMND_ABORT 0
- #define CMND_START_PVT_DATA 49
- #define CMND_STOP_PVT_DATA 50
- #define CMND_START_RM_DATA 110
- #define MAX_BUFFER_SIZE 4096
- #define GARMIN_CHANNELS 12
- #define ASYNC_DATA_SIZE 64
- #pragma pack(1)
- typedef struct __attribute__((__packed__))
- {
- uint8_t svid;
- uint16_t snr;
- uint8_t elev;
- uint16_t azmth;
- uint8_t status;
-
-
- } cpo_sat_data;
- typedef struct __attribute__((__packed__))
- {
- float alt;
- float epe;
- float eph;
- float epv;
- int16_t fix;
- double gps_tow;
- double lat;
- double lon;
- float lon_vel;
- float lat_vel;
- float alt_vel;
-
-
- float msl_hght;
- int16_t leap_sec;
- int32_t grmn_days;
- } cpo_pvt_data;
- typedef struct __attribute__((__packed__))
- {
- uint32_t cycles;
- double pr;
- uint16_t phase;
- int8_t slp_dtct;
- uint8_t snr_dbhz;
- uint8_t svid;
- int8_t valid;
- } cpo_rcv_sv_data;
- typedef struct __attribute__((__packed__))
- {
- double rcvr_tow;
- int16_t rcvr_wn;
- cpo_rcv_sv_data sv[GARMIN_CHANNELS];
- } cpo_rcv_data;
- typedef struct __attribute__((__packed__))
- {
- uint8_t mPacketType;
- uint8_t mReserved1;
- uint16_t mReserved2;
- uint16_t mPacketId;
- uint16_t mReserved3;
- uint32_t mDataSize;
- union
- {
-
-
- uint8_t uchars[MAX_BUFFER_SIZE];
- cpo_pvt_data pvt;
- cpo_sat_data sats;
- } mData;
- } Packet_t;
- static inline void set_int16(uint8_t * buf, uint32_t value)
- {
- buf[0] = (uint8_t) (0x0FF & value);
- buf[1] = (uint8_t) (0x0FF & (value >> 8));
- }
- static inline void set_int32(uint8_t * buf, uint32_t value)
- {
- buf[0] = (uint8_t) (0x0FF & value);
- buf[1] = (uint8_t) (0x0FF & (value >> 8));
- buf[2] = (uint8_t) (0x0FF & (value >> 16));
- buf[3] = (uint8_t) (0x0FF & (value >> 24));
- }
- static inline uint16_t get_uint16(const uint8_t * buf)
- {
- return (uint16_t) (0xFF & buf[0])
- | ((uint16_t) (0xFF & buf[1]) << 8);
- }
- #if defined(HAVE_LIBUSB) && defined(__linux__)
- static inline uint32_t get_int32(const uint8_t * buf)
- {
- return (uint32_t) (0xFF & buf[0])
- | ((uint32_t) (0xFF & buf[1]) << 8)
- | ((uint32_t) (0xFF & buf[2]) << 16)
- | ((uint32_t) (0xFF & buf[3]) << 24);
- }
- #endif
- static inline double radtodeg(double rad)
- {
- return (double)(rad * RAD_2_DEG);
- }
- static gps_mask_t PrintSERPacket(struct gps_device_t *session,
- unsigned char pkt_id, int pkt_len,
- unsigned char *buf);
- #if defined(HAVE_LIBUSB) && defined(__linux__)
- static gps_mask_t PrintUSBPacket(struct gps_device_t *session,
- Packet_t * pkt);
- #endif
- gps_mask_t PrintSERPacket(struct gps_device_t *session, unsigned char pkt_id,
- int pkt_len, unsigned char *buf)
- {
- gps_mask_t mask = ONLINE_SET;
- int i = 0, j = 0;
- uint16_t prod_id = 0;
- uint16_t ver = 0;
- int maj_ver;
- int min_ver;
- time_t time_l = 0;
- char msg_buf[512] = "";
- char *msg = NULL;
- cpo_sat_data *sats = NULL;
- cpo_pvt_data *pvt = NULL;
- cpo_rcv_data *rmd = NULL;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: PrintSERPacket(, %#02x, %#02x, )\n", pkt_id, pkt_len);
- session->cycle_end_reliable = true;
- switch (pkt_id) {
- case ACK:
- GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: ACK\n");
- break;
- case NAK:
- GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: NAK\n");
- break;
- case GARMIN_PKTID_L001_COMMAND_DATA:
- prod_id = get_uint16((uint8_t *) buf);
- switch (prod_id) {
- case CMND_ABORT:
- msg = "Abort current xfer";
- break;
- case CMND_START_PVT_DATA:
- msg = "Start Xmit PVT data";
- break;
- case CMND_STOP_PVT_DATA:
- msg = "Stop Xmit PVT data";
- break;
- case CMND_START_RM_DATA:
- msg = "Start RMD data";
- break;
- default:
- (void)snprintf(msg_buf, sizeof(msg_buf), "Unknown: %u",
- (unsigned int)prod_id);
- msg = msg_buf;
- break;
- }
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Appl, Command Data: %s\n", msg);
- break;
- case GARMIN_PKTID_PRODUCT_RQST:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Appl, Product Data req\n");
- break;
- case GARMIN_PKTID_PRODUCT_DATA:
- prod_id = get_uint16((uint8_t *) buf);
- ver = get_uint16((uint8_t *) & buf[2]);
- maj_ver = (int)(ver / 100);
- min_ver = (int)(ver - (maj_ver * 100));
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Appl, Product Data, sz: %d\n",
- pkt_len);
- (void)snprintf(session->subtype, sizeof(session->subtype),
- "%d: %d.%02d", (int)prod_id, maj_ver, min_ver);
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Product ID: %d, SoftVer: %d.%02d\n",
- prod_id, maj_ver, min_ver);
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Product Desc: %s\n", &buf[4]);
- mask |= DEVICEID_SET;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: PRODUCT_DATA: subtype=%s\n",
- session->subtype);
- break;
- case GARMIN_PKTID_PVT_DATA:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Appl, PVT Data Sz: %d\n", pkt_len);
- pvt = (cpo_pvt_data *) buf;
-
- time_l = (time_t) (631065600 + (GPSD_LE32TOH(pvt->grmn_days) * 86400));
-
- time_l -= GPSD_LE16TOH(pvt->leap_sec);
- session->context->leap_seconds = (int)GPSD_LE16TOH(pvt->leap_sec);
- session->context->valid = LEAP_SECOND_VALID;
-
-
- time_l += (time_t) round(pvt->gps_tow);
- DTOTS(&session->context->gps_tow, pvt->gps_tow);
- session->newdata.time.tv_sec = time_l;
- session->newdata.time.tv_nsec = 0;
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: time_l: %ld\n", (long int)time_l);
- session->newdata.latitude = radtodeg(pvt->lat);
- session->newdata.longitude = radtodeg(pvt->lon);
-
- session->newdata.altHAE = pvt->alt;
-
-
- session->newdata.geoid_sep = -pvt->msl_hght;
-
- session->newdata.sep = pvt->epe * (GPSD_CONFIDENCE / CEP50_SIGMA);
-
- session->newdata.eph = pvt->eph * (GPSD_CONFIDENCE / CEP50_SIGMA);
-
- session->newdata.epv = pvt->epv * (GPSD_CONFIDENCE / CEP50_SIGMA);
-
- session->newdata.NED.velN = pvt->lat_vel;
- session->newdata.NED.velE = pvt->lon_vel;
- session->newdata.NED.velD = -pvt->alt_vel;
- switch (GPSD_LE16TOH(pvt->fix)) {
- case 0:
- case 1:
- default:
-
- session->gpsdata.status = STATUS_NO_FIX;
- session->newdata.mode = MODE_NO_FIX;
- break;
- case 2:
-
- session->gpsdata.status = STATUS_FIX;
- session->newdata.mode = MODE_2D;
- break;
- case 3:
-
- session->gpsdata.status = STATUS_FIX;
- session->newdata.mode = MODE_3D;
- break;
- case 4:
-
- session->gpsdata.status = STATUS_DGPS_FIX;
- session->newdata.mode = MODE_2D;
- break;
- case 5:
-
- session->gpsdata.status = STATUS_DGPS_FIX;
- session->newdata.mode = MODE_3D;
- break;
- }
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Appl, mode %d, status %d\n",
- session->newdata.mode, session->gpsdata.status);
-
- if (session->context->errout.debug >= LOG_INF) {
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: UTC Time: %lld\n",
- (long long)session->newdata.time.tv_sec);
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Geoid Separation (MSL-WGS84): from garmin %lf, "
- "calculated %lf\n",
- -pvt->msl_hght,
- wgs84_separation(session->newdata.latitude,
- session->newdata.longitude));
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Alt: %.3f, Epe: %.3f, Eph: %.3f, Epv: %.3f, "
- "Fix: %d, Gps_tow: %f, Lat: %.3f, Lon: %.3f, "
- "LonVel: %.3f, LatVel: %.3f, AltVel: %.3f, MslHgt: %.3f, "
- "Leap: %d, GarminDays: %d\n",
- pvt->alt, pvt->epe, pvt->eph, pvt->epv,
- GPSD_LE16TOH(pvt->fix),
- pvt->gps_tow, session->newdata.latitude,
- session->newdata.longitude, pvt->lon_vel, pvt->lat_vel,
- pvt->alt_vel, pvt->msl_hght, GPSD_LE16TOH(pvt->leap_sec),
- GPSD_LE32TOH(pvt->grmn_days));
- }
- if (session->newdata.mode > MODE_NO_FIX) {
-
- mask |=
- TIME_SET | LATLON_SET | ALTITUDE_SET | STATUS_SET | MODE_SET |
- HERR_SET | PERR_IS | CLEAR_IS | REPORT_IS | VNED_SET;
-
- if (session->fixcnt > 3)
- mask |= NTPTIME_IS;
- }
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: PVT_DATA: time=%lld, lat=%.2f lon=%.2f "
- "eph=%.2f sep=%.2f epv=%.2f mode=%d status=%d\n",
- (long long)session->newdata.time.tv_sec,
- session->newdata.latitude,
- session->newdata.longitude,
- session->newdata.eph,
- session->newdata.sep,
- session->newdata.epv,
- session->newdata.mode,
- session->gpsdata.status);
- break;
- case GARMIN_PKTID_RMD_DATA:
- case GARMIN_PKTID_RMD41_DATA:
- rmd = (cpo_rcv_data *) buf;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: PVT RMD Data Sz: %d\n", pkt_len);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: PVT RMD rcvr_tow: %f, rcvr_wn: %d\n",
- rmd->rcvr_tow, rmd->rcvr_wn);
- for (i = 0; i < GARMIN_CHANNELS; i++) {
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: PVT RMD Sat: %3u, cycles: %9u, pr: %16.6f, "
- "phase: %7.3f, slp_dtct: %3s, snr: %3u, Valid: %3s\n",
- (int)rmd->sv[i].svid + 1,
- GPSD_LE32TOH(rmd->sv[i].cycles),
- rmd->sv[i].pr,
- (GPSD_LE16TOH(rmd->sv[i].phase) * 360.0) / 2048.0,
- rmd->sv[i].slp_dtct != 0 ? "Yes" : "No",
- rmd->sv[i].snr_dbhz,
- rmd->sv[i].valid != 0 ? "Yes" : "No");
- }
- break;
- case GARMIN_PKTID_SAT_DATA:
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: SAT Data Sz: %d\n", pkt_len);
- sats = (cpo_sat_data *) buf;
- session->gpsdata.satellites_used = 0;
- gpsd_zero_satellites(&session->gpsdata);
- for (i = 0, j = 0; i < GARMIN_CHANNELS; i++, sats++) {
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Sat %2d, snr: %5u, elev: %2d, Azmth: %3d, "
- "Stat: x%x\n",
- sats->svid, GPSD_LE16TOH(sats->snr), sats->elev,
- GPSD_LE16TOH(sats->azmth),
- sats->status);
- if (255 == (int)sats->svid) {
-
-
- continue;
- }
- if ((int)sats->svid <= 32) {
-
- session->gpsdata.skyview[j].PRN = (short)sats->svid;
- } else {
-
- session->gpsdata.skyview[j].PRN = (short)sats->svid + 87;
- }
- session->gpsdata.skyview[j].azimuth =
- (short)GPSD_LE16TOH(sats->azmth);
- session->gpsdata.skyview[j].elevation = (short)sats->elev;
- if (0xffff == sats->snr) {
- session->gpsdata.skyview[j].ss = NAN;
- } else {
-
-
- session->gpsdata.skyview[j].ss =
- (float)(GPSD_LE16TOH(sats->snr) / 100.0);
- }
-
-
-
- if ((uint8_t) 0 != (sats->status & 4)) {
-
- session->gpsdata.skyview[j].used = true;
- session->gpsdata.satellites_used++;
- }
- session->gpsdata.satellites_visible++;
- j++;
- }
- session->gpsdata.skyview_time.tv_sec = 0;
- session->gpsdata.skyview_time.tv_nsec = 0;
- mask |= USED_IS | SATELLITE_SET;
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: SAT_DATA: visible=%d used=%d\n",
- session->gpsdata.satellites_visible,
- session->gpsdata.satellites_used);
- break;
- case GARMIN_PKTID_PROTOCOL_ARRAY:
-
-
-
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: Appl, Product Capability, sz: %d\n",
- pkt_len);
- for (i = 0; i < pkt_len; i += 3) {
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: %c%03d\n",
- buf[i], get_uint16((uint8_t *) & buf[i + 1]));
- }
- break;
- default:
- GPSD_LOG(LOG_WARN, &session->context->errout,
- "Garmin: Unknown packet id: %#02x, Sz: %#02x\n",
- pkt_id, pkt_len);
- break;
- }
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: PrintSERPacket(, %#02x, %#02x, ) mask=(%s)\n",
- pkt_id, pkt_len, gps_maskdump(mask));
- return mask;
- }
- #if defined(HAVE_LIBUSB) && defined(__linux__)
- static gps_mask_t PrintUSBPacket(struct gps_device_t *session, Packet_t * pkt)
- {
- gps_mask_t mask = 0;
- int maj_ver;
- int min_ver;
- uint32_t mode = 0;
- uint16_t prod_id = 0;
- uint32_t veri = 0;
- uint32_t serial;
- uint32_t mDataSize = get_int32((uint8_t *) & pkt->mDataSize);
- uint8_t *buffer = (uint8_t *) pkt;
- GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: PrintUSBPacket()\n");
- if (DLE == pkt->mPacketType) {
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: really a SER packet!\n");
- return PrintSERPacket(session,
- (unsigned char)buffer[1],
- (int)buffer[2], (unsigned char *)(buffer + 3));
- }
- if (4096 < mDataSize) {
- GPSD_LOG(LOG_WARN, &session->context->errout,
- "Garmin: bogus packet, size too large=%d\n",
- mDataSize);
- return 0;
- }
- switch (pkt->mPacketType) {
- case GARMIN_LAYERID_TRANSPORT:
-
- switch (pkt->mPacketId) {
- case GARMIN_PKTID_TRANSPORT_START_SESSION_REQ:
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Transport, Start Session req\n");
- break;
- case GARMIN_PKTID_TRANSPORT_START_SESSION_RESP:
-
- mode = get_int32(&pkt->mData.uchars[0]);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Transport, Start Session resp, unit: 0x%x\n",
- mode);
- break;
- default:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Transport, Packet: Type %d %d %d, ID: %d,"
- "Sz: %d\n",
- pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
- pkt->mPacketId, mDataSize);
- break;
- }
- break;
- case GARMIN_LAYERID_APPL:
-
- mask = PrintSERPacket(session,
- (unsigned char)pkt->mPacketId,
- (int)mDataSize,
- (unsigned char *)pkt->mData.uchars);
- break;
- case 75:
-
- switch (pkt->mPacketId) {
- case PRIV_PKTID_SET_MODE:
- prod_id = get_uint16(&pkt->mData.uchars[0]);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Private, Set Mode: %d\n", prod_id);
- break;
- case PRIV_PKTID_INFO_REQ:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Private, ID: Info Req\n");
- break;
- case PRIV_PKTID_INFO_RESP:
- veri = get_int32(pkt->mData.uchars);
- maj_ver = (int)(veri >> 16);
- min_ver = (int)(veri & 0xffff);
- mode = get_int32(&pkt->mData.uchars[4]);
- serial = get_int32(&pkt->mData.uchars[8]);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Private, ID: Info Resp\n");
- GPSD_LOG(LOG_INF, &session->context->errout,
- "Garmin: USB Driver found, Version %d.%d, Mode: %d, GPS Serial# %u\n",
- maj_ver, min_ver, mode, serial);
- break;
- default:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Private, Packet: ID: %d, Sz: %d\n",
- pkt->mPacketId, mDataSize);
- break;
- }
- break;
- default:
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Packet: Type %d %d %d, ID: %d, Sz: %d\n",
- pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
- pkt->mPacketId, mDataSize);
- break;
- }
- return mask;
- }
- #endif
- #if defined(HAVE_LIBUSB) && defined(__linux__)
- static void Build_Send_USB_Packet(struct gps_device_t *session,
- uint32_t layer_id, uint32_t pkt_id,
- uint32_t length, uint32_t data)
- {
- uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
- Packet_t *thePacket = (Packet_t *) buffer;
- ssize_t theBytesReturned = 0;
- ssize_t theBytesToWrite = 12 + (ssize_t) length;
- set_int32(buffer, layer_id);
- set_int32(buffer + 4, pkt_id);
- set_int32(buffer + 8, length);
- if (2 == length) {
- set_int16(buffer + 12, data);
- } else if (4 == length) {
- set_int32(buffer + 12, data);
- }
- (void)PrintUSBPacket(session, thePacket);
- theBytesReturned = gpsd_write(session, (const char *)thePacket,
- (size_t) theBytesToWrite);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: SendPacket(), wrote %zd bytes\n",
- theBytesReturned);
-
-
-
-
-
-
- if (0 == (theBytesToWrite % ASYNC_DATA_SIZE)) {
- char *n = "";
- (void)gpsd_write(session, n, 0);
- }
- }
- #endif
- static void Build_Send_SER_Packet(struct gps_device_t *session,
- uint32_t layer_id UNUSED, uint32_t pkt_id,
- uint32_t length, uint32_t data)
- {
- uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
- uint8_t *buffer0 = buffer;
- Packet_t *thePacket = (Packet_t *) buffer;
- ssize_t theBytesReturned = 0;
- ssize_t theBytesToWrite = 6 + (ssize_t) length;
- uint8_t chksum = 0;
- *buffer++ = (uint8_t) DLE;
- *buffer++ = (uint8_t) pkt_id;
- chksum = pkt_id;
- *buffer++ = (uint8_t) length;
- chksum += length;
-
- if (2 == length) {
-
- set_int16(buffer, data);
- chksum += buffer[0];
- chksum += buffer[1];
- } else if (4 == length) {
-
- set_int32(buffer, data);
- chksum += buffer[0];
- chksum += buffer[1];
- chksum += buffer[2];
- chksum += buffer[3];
- }
-
- buffer += length;
-
- *buffer++ = -chksum;
- if (DLE == -chksum) {
-
- *buffer++ = (uint8_t) DLE;
- theBytesToWrite++;
- }
-
- *buffer++ = (uint8_t) DLE;
-
- *buffer = (uint8_t) ETX;
- (void)PrintSERPacket(session,
- (unsigned char)buffer0[1],
- (int)buffer0[2], (unsigned char *)(buffer0 + 3));
- theBytesReturned = gpsd_write(session, (const char *)thePacket,
- (size_t) theBytesToWrite);
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: SendPacket(), wrote %zd bytes\n",
- theBytesReturned);
- }
- #if defined(HAVE_LIBUSB) && defined(__linux__)
- static bool is_usb_device(const char *path UNUSED, int vendor, int product,
- struct gpsd_errout_t *errout)
- {
-
- libusb_device **list;
- ssize_t cnt;
- ssize_t i = 0;
- bool found = false;
- GPSD_LOG(LOG_INF, errout, "attempting USB device enumeration.\n");
- (void)libusb_init(NULL);
- if ((cnt = libusb_get_device_list(NULL, &list)) < 0) {
- GPSD_LOG(LOG_ERROR, errout, "USB device list call failed.\n");
- libusb_exit(NULL);
- return false;
- }
- for (i = 0; i < cnt; i++) {
- struct libusb_device_descriptor desc;
- libusb_device *dev = list[i];
- int r = libusb_get_device_descriptor(dev, &desc);
- if (r < 0) {
- GPSD_LOG(LOG_ERROR, errout,
- "USB descriptor fetch failed on device %zd.\n", i);
- continue;
- }
-
- GPSD_LOG(LOG_INF, errout,
- "%04x:%04x (bus %d, device %d)\n",
- desc.idVendor, desc.idProduct,
- libusb_get_bus_number(dev),
- libusb_get_device_address(dev));
-
- if (desc.idVendor == (uint16_t)vendor && desc.idProduct == (uint16_t)product) {
- found = true;
- break;
- }
- }
- GPSD_LOG(LOG_INF, errout,
- "vendor/product match with %04x:%04x %sfound\n",
- vendor, product, found ? "" : "not ");
- libusb_free_device_list(list, 1);
- libusb_exit(NULL);
- return found;
- }
- #endif
- static bool garmin_usb_detect(struct gps_device_t *session UNUSED)
- {
- #if defined(__linux__)
-
- if (session->sourcetype != source_usb)
- return false;
- else {
- #ifdef HAVE_LIBUSB
- if (!is_usb_device(session->gpsdata.dev.path, 0x091e, 0x0003,
- &session->context->errout))
- return false;
- if (!gpsd_set_raw(session)) {
- GPSD_LOG(LOG_ERROR, &session->context->errout,
- "Garmin: garmin_usb_detect: error changing port attributes: %s\n",
- strerror(errno));
- return false;
- }
- if (sizeof(session->driver.garmin.Buffer) < sizeof(Packet_t)) {
-
- GPSD_LOG(LOG_ERROR, &session->context->errout,
- "Garmin: garmin_usb_detect: Compile error, garmin.Buffer too small.\n");
- return false;
- }
-
-
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Set garmin_gps driver mode = 0\n");
- Build_Send_USB_Packet(session, GARMIN_LAYERID_PRIVATE,
- PRIV_PKTID_SET_MODE, 4, MODE_GARMIN_SERIAL);
-
- return true;
- #else
- return false;
- #endif
- }
- #else
- return false;
- #endif
- }
- static void garmin_event_hook(struct gps_device_t *session, event_t event)
- {
- if (session->context->readonly)
- return;
-
- if (event == event_identified || event == event_reactivate) {
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Get Product Data\n");
- Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
- GARMIN_PKTID_PRODUCT_RQST, 0, 0);
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Set to send reports every 1 second\n");
- Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
- GARMIN_PKTID_L001_COMMAND_DATA, 2,
- CMND_START_PVT_DATA);
- #if USE_RMD
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: Set to send Raw sat data\n");
- Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
- GARMIN_PKTID_L001_COMMAND_DATA, 2,
- CMND_START_RM_DATA);
- #endif
- }
- if (event == event_deactivate)
-
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: garmin_close()\n");
- }
- #define Send_ACK() Build_Send_SER_Packet(session, 0, ACK, 0, 0)
- #define Send_NAK() Build_Send_SER_Packet(session, 0, NAK, 0, 0)
- gps_mask_t garmin_ser_parse(struct gps_device_t *session)
- {
- unsigned char *buf = session->lexer.outbuffer;
- size_t len = session->lexer.outbuflen;
- unsigned char data_buf[MAX_BUFFER_SIZE];
- unsigned char c;
- int i = 0;
- size_t n = 0;
- int data_index = 0;
- int got_dle = 0;
- unsigned char pkt_id = 0;
- unsigned char pkt_len = 0;
- unsigned char chksum = 0;
- gps_mask_t mask = 0;
- struct timespec delay;
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: garmin_ser_parse()\n");
- if (6 > len) {
-
-
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: serial too short: %zd\n", len);
- return 0;
- }
-
- for (i = 0; i < (int)len; i++) {
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Char: %#02x\n", buf[i]);
- }
- if ('\x10' != buf[0]) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: buf[0] not DLE\n");
- return 0;
- }
- n = 1;
- pkt_id = buf[n++];
- chksum = pkt_id;
- if ('\x10' == pkt_id) {
- if ('\x10' != buf[n++]) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Bad pkt_id %#02x\n", pkt_id);
- return 0;
- }
- }
- pkt_len = buf[n++];
- chksum += pkt_len;
- if ('\x10' == pkt_len) {
- if ('\x10' != buf[n++]) {
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Bad pkt_len %#02x\n", pkt_len);
- Send_NAK();
- return 0;
- }
- }
- data_index = 0;
- for (i = 0; i < 256; i++) {
- if ((int)pkt_len == data_index) {
-
- break;
- }
- if (len < n + i) {
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Packet too short %zd < %zd\n",
- len, n + i);
- Send_NAK();
- return 0;
- }
- c = buf[n + i];
- if (got_dle) {
- got_dle = 0;
- if ('\x10' != c) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Bad DLE %#02x\n", c);
- return 0;
- }
- } else {
- chksum += c;
- data_buf[data_index++] = c;
- if ('\x10' == c) {
- got_dle = 1;
- }
- }
- }
-
- if (len < n + i) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: No checksum, Packet too short %zd < %zd\n", len,
- n + i);
- return 0;
- }
- c = buf[n + i++];
- chksum += c;
-
- if (len < n + i) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: No final DLE, Packet too short %zd < %zd\n", len,
- n + i);
- return 0;
- }
- c = buf[n + i++];
- if ('\x10' != c) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Final DLE not DLE\n");
- return 0;
- }
-
- if (len < n + i) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: No final ETX, Packet too short %zd < %zd\n", len,
- n + i);
- return 0;
- }
-
- c = buf[n + i];
- if ('\x03' != c) {
- Send_NAK();
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Final ETX not ETX\n");
- return 0;
- }
-
- for (i = 0; i < data_index; i++) {
- GPSD_LOG(LOG_RAW, &session->context->errout,
- "Garmin: Char: %#02x\n", data_buf[i]);
- }
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: garmin_ser_parse() Type: %#02x, Len: %#02x, chksum: %#02x\n",
- pkt_id, pkt_len, chksum);
- mask = PrintSERPacket(session, pkt_id, pkt_len, data_buf);
-
-
-
- delay.tv_sec = 0;
- delay.tv_nsec = 300000L;
- nanosleep(&delay, NULL);
- Send_ACK();
- GPSD_LOG(LOG_DATA, &session->context->errout,
- "Garmin: garmin_ser_parse( )\n");
- return mask;
- }
- #ifdef RECONFIGURE_ENABLE
- static void settle(void)
- {
- struct timespec delay, rem;
- memset(&delay, 0, sizeof(delay));
- delay.tv_sec = 0;
- delay.tv_nsec = 333000000L;
- nanosleep(&delay, &rem);
- }
- static void garmin_switcher(struct gps_device_t *session, int mode)
- {
- if (mode == MODE_NMEA) {
- const unsigned char switcher[] =
- { 0x10, 0x0A, 0x02, 0x26, 0x00, 0xCE, 0x10, 0x03 };
-
- ssize_t status = gpsd_write(session, (char *)switcher,
- sizeof(switcher));
- if (status == (ssize_t)sizeof(switcher)) {
- GPSD_LOG(LOG_PROG, &session->context->errout,
- "Garmin: => GPS: turn off binary %02x %02x %02x... \n",
- switcher[0], switcher[1], switcher[2]);
- } else {
- GPSD_LOG(LOG_ERROR, &session->context->errout,
- "Garmin: => GPS: FAILED\n");
- }
- settle();
-
- (void)nmea_send(session, "$PGRMC1,1,1");
-
- (void)nmea_send(session, "$PGRMI,,,,,,,R");
- settle();
- } else {
- (void)nmea_send(session, "$PGRMC1,1,2,1,,,,2,W,N");
- (void)nmea_send(session, "$PGRMI,,,,,,,R");
- settle();
- }
- }
- #endif
- #ifdef CONTROLSEND_ENABLE
- static ssize_t garmin_control_send(struct gps_device_t *session,
- char *buf, size_t buflen)
- {
- session->msgbuflen = buflen;
- (void)memcpy(session->msgbuf, buf, buflen);
- return gpsd_write(session, session->msgbuf, session->msgbuflen);
- }
- #endif
- static double garmin_time_offset(struct gps_device_t *session)
- {
- if (session->sourcetype == source_usb) {
- return 0.035;
- }
-
-
- switch (session->gpsdata.dev.baudrate) {
- case 4800:
- return 0.430;
- case 9600:
- return 0.430;
- case 19200:
- return 0.430;
- case 38400:
- return 0.430;
- }
- return 0.430;
- }
- const struct gps_type_t driver_garmin_usb_binary =
- {
- .type_name = "Garmin USB binary",
- .packet_type = GARMIN_PACKET,
- .flags = DRIVER_STICKY,
- .trigger = NULL,
- .channels = GARMIN_CHANNELS,
- .probe_detect = garmin_usb_detect,
- .get_packet = generic_get,
- .parse_packet = garmin_ser_parse,
- .rtcm_writer = NULL,
- .init_query = NULL,
- .event_hook = garmin_event_hook,
- #ifdef RECONFIGURE_ENABLE
- .speed_switcher = NULL,
- .mode_switcher = NULL,
- .rate_switcher = NULL,
- .min_cycle.tv_sec = 0,
- .min_cycle.tv_nsec = 10000000,
- #endif
- #ifdef CONTROLSEND_ENABLE
- .control_send = garmin_control_send,
- #endif
- .time_offset = garmin_time_offset,
- };
- const struct gps_type_t driver_garmin_ser_binary =
- {
- .type_name = "Garmin Serial binary",
- .packet_type = GARMIN_PACKET,
- .flags = DRIVER_STICKY,
- .trigger = NULL,
- .channels = GARMIN_CHANNELS,
- .probe_detect = NULL,
- .get_packet = generic_get,
- .parse_packet = garmin_ser_parse,
- .rtcm_writer = NULL,
- .init_query = NULL,
- .event_hook = NULL,
- #ifdef RECONFIGURE_ENABLE
- .speed_switcher = NULL,
- .mode_switcher = garmin_switcher,
- .rate_switcher = NULL,
- .min_cycle.tv_sec = 0,
- .min_cycle.tv_nsec = 10000000,
- #endif
- #ifdef CONTROLSEND_ENABLE
- .control_send = garmin_control_send,
- #endif
- .time_offset = garmin_time_offset,
- };
- #endif
|