1 /*
2  * This file contains two drivers for Garmin receivers and some code
3  * shared by both drivers.
4  *
5  * One driver "garmin_usb_binary" handles the Garmin binary packet
6  * format supported by the USB Garmins tested with the Garmin 18 and
7  * other models.  (There is also "garmin_usb_binary_old".)  These are ONLY
8  * for USB devices reporting as: 091e:0003.
9  *
10  * The other driver "garmin_ser_binary" is for Garmin receivers via a
11  * serial port, whether or not one uses a USB/serial adaptor or a real
12  * serial port.  These receivers provide adequate NMEA support, so it
13  * often makes sense to just put them into NMEA mode.
14  *
15  * On Linux, USB Garmins (091e:0003) need the Linux garmin_gps driver and
16  * will not function without it.  On other operating systems, it is clear
17  * garmin_usb_binary_old does not work since it requires the Linux
18  * garmin_gps module.
19  *
20  * This code has been tested and at least at one time is known to work on
21  * big- and little-endian CPUs and 32 and 64 bit cpu modes.
22  *
23  *
24  * Documentation for the Garmin protocols can be found via
25  *   http://www.garmin.com/support/commProtocol.html
26  * The file IOSDK.zip contains IntfSpec.pdf, which describes the
27  * protocol in terms of Application, Link, and Physical.  This
28  * identical file is also available at:
29  *   http://www.garmin.com/support/pdf/iop_spec.pdf
30  * An older version of iop_spec.pdf that describes only Serial Binary
31  * is available at:
32  *   http://vancouver-webpages.com/pub/peter/iop_spec.pdf
33  * Information about the GPS 18
34  *   http://www.garmin.com/manuals/425_TechnicalSpecification.pdf
35  *
36  * There is one physical link protocol for serial which uses DLE/ETX
37  * framing.  There is another physical protocol for USB which relies
38  * on the packetization intrinsic to USB bulk pipes.
39  *
40  * There are several link protocols; all devices implement L000.
41  * There are then product-specific protocols; most devices implement
42  * L001.  Link protocols are the same and carried over either Physical
43  * protocol.
44  *
45  * Application protocols are named A000 and then with different
46  * 3-digit numbers.  They are carried over Link protocols.
47  *
48  * Thus, much of the higher-level code dealing the data formats is
49  * shared between USB Binary and Serial Binary.
50  *
51  * This code is partly from the Garmin IOSDK and partly from the
52  * sample code in the Linux garmin_gps driver.
53  *
54  * bad code by: Gary E. Miller <gem@rellim.com>
55  *
56  * -D 3 = packet trace
57  * -D 4 = packet details
58  * -D 5 = more packet details
59  * -D 6 = very excessive details
60  *
61  * limitations:
62  *
63  * do not have from garmin:
64  *      pdop
65  *      hdop
66  *      vdop
67  *	magnetic variation
68  *
69  * known bugs:
70  *      hangs in the fread loop instead of keeping state and returning.
71  *
72  * TODO:
73  *
74  *	?? Add probe function for Serial Binary to start PVT output.
75  *
76  * This file is Copyright (c) 2010-2019 by the GPSD project
77  * SPDX-License-Identifier: BSD-2-clause
78  */
79 
80 #include "gpsd_config.h"  /* must be before all includes */
81 
82 #ifdef GARMIN_ENABLE
83 
84 #include <errno.h>
85 #include <math.h>
86 #include <stdbool.h>
87 #include <stdio.h>
88 #include <string.h>
89 #include <time.h>
90 #include <unistd.h>
91 
92 #if defined(HAVE_LIBUSB)
93 #include <libusb.h>
94 #endif
95 
96 #include "gpsd.h"
97 #include "bits.h"
98 #include "timespec.h"
99 
100 #define GPSD_LE16TOH(x) getles16((char *)(&(x)), 0)
101 #define GPSD_LE32TOH(x) getles32((char *)(&(x)), 0)
102 #define GPSD_LEF32(x) getlef32((const char *)(&(x)), 0)
103 #define GPSD_LED64(x) getled64((const char *)(&(x)), 0)
104 
105 #define USE_RMD 0
106 
107 /* Used in Serial Physical Layer */
108 #define ETX 0x03
109 #define ACK 0x06
110 #define DLE 0x10
111 #define NAK 0x15
112 
113 #define GARMIN_LAYERID_TRANSPORT (uint8_t)  0
114 #define GARMIN_LAYERID_APPL      (uint32_t) 20
115 // Linux Garmin USB driver layer-id to use for some control mechanisms
116 #define GARMIN_LAYERID_PRIVATE  0x01106E4B
117 
118 // packet ids used in private layer
119 #define PRIV_PKTID_SET_DEBUG    1
120 #define PRIV_PKTID_SET_MODE     2
121 #define PRIV_PKTID_INFO_REQ     3
122 #define PRIV_PKTID_INFO_RESP    4
123 #define PRIV_PKTID_RESET_REQ    5
124 #define PRIV_PKTID_SET_DEF_MODE 6
125 
126 #define MODE_NATIVE	  0
127 #define MODE_GARMIN_SERIAL   1
128 
129 #define GARMIN_PKTID_TRANSPORT_START_SESSION_REQ 5
130 #define GARMIN_PKTID_TRANSPORT_START_SESSION_RESP 6
131 
132 #define GARMIN_PKTID_PROTOCOL_ARRAY     253
133 #define GARMIN_PKTID_PRODUCT_RQST       254
134 #define GARMIN_PKTID_PRODUCT_DATA       255
135 /* 0x29 ')' */
136 #define GARMIN_PKTID_RMD41_DATA	 41
137 /* 0x33 '3' */
138 #define GARMIN_PKTID_PVT_DATA	   51
139 /* 0x33 '4' */
140 #define GARMIN_PKTID_RMD_DATA	   52
141 /* 0x72 'r' */
142 #define GARMIN_PKTID_SAT_DATA	   114
143 
144 #define GARMIN_PKTID_L001_XFER_CMPLT     12
145 #define GARMIN_PKTID_L001_COMMAND_DATA   10
146 #define GARMIN_PKTID_L001_DATE_TIME_DATA 14
147 #define GARMIN_PKTID_L001_RECORDS	27
148 #define GARMIN_PKTID_L001_WPT_DATA       35
149 
150 #define	CMND_ABORT			 0
151 #define	CMND_START_PVT_DATA		 49
152 #define	CMND_STOP_PVT_DATA		 50
153 #define	CMND_START_RM_DATA		 110
154 
155 #define MAX_BUFFER_SIZE 4096
156 
157 #define GARMIN_CHANNELS	12
158 
159 // something magic about 64, garmin driver will not return more than
160 // 64 at a time.  If you read less than 64 bytes the next read will
161 // just get the last of the 64 byte buffer.
162 #define ASYNC_DATA_SIZE 64
163 
164 
165 #pragma pack(1)
166 // This is the data format of the satellite data from the garmin USB
167 typedef struct __attribute__((__packed__))
168 {
169     uint8_t svid;
170     uint16_t snr;		// 0 - 0xffff
171     uint8_t elev;
172     uint16_t azmth;
173     uint8_t status;		// bit 0, has ephemeris, 1, has diff correction
174     // bit 2 used in solution
175     // bit 3??
176 } cpo_sat_data;
177 
178 /* Garmin D800_Pvt_Datetype_Type */
179 /* packet type:  GARMIN_PKTID_PVT_DATA   52 */
180 /* This is the data format of the position data from the garmin USB */
181 typedef struct __attribute__((__packed__))
182 {
183     float alt;			/* altitude above WGS 84 (meters) */
184     float epe;			/* estimated position error, 2 sigma (meters) */
185     float eph;			/* epe, but horizontal only (meters) */
186     float epv;			/* epe but vertical only (meters ) */
187     int16_t fix;		/* 0 - failed integrity check
188 				 * 1 - invalid or unavailable fix
189 				 * 2 - 2D
190 				 * 3 - 3D
191 				 * 4 - 2D Diff
192 				 * 5 - 3D Diff
193 				 */
194     double gps_tow;		/* gps time of week (seconds) */
195     double lat;			/* ->latitude (radians) */
196     double lon;			/* ->longitude (radians) */
197     float lon_vel;		/* velocity east (meters/second) */
198     float lat_vel;		/* velocity north (meters/second) */
199     float alt_vel;		/* velocity up (meters/sec) */
200     // Garmin GPS25 uses pkt_id 0x28 and does not output the
201     // next 3 items
202     float msl_hght;		/* height of WGS 84 above MSL (meters) */
203     int16_t leap_sec;		/* diff between GPS and UTC (seconds) */
204     int32_t grmn_days;		/* days from UTC December 31st, 1989 to the
205 				 * beginning of the current week */
206 } cpo_pvt_data;
207 
208 typedef struct __attribute__((__packed__))
209 {
210     uint32_t cycles;
211     double pr;                  // psuedorange in meters
212     uint16_t phase;
213     int8_t slp_dtct;
214     uint8_t snr_dbhz;
215     uint8_t svid;
216     int8_t valid;
217 } cpo_rcv_sv_data;
218 
219 /* packet type:  GARMIN_PKTID_RMD_DATA   53 */
220 /* seems identical to the packet id 0x29 from the Garmin GPS 25 */
221 typedef struct __attribute__((__packed__))
222 {
223     double rcvr_tow;
224     int16_t rcvr_wn;
225     cpo_rcv_sv_data sv[GARMIN_CHANNELS];
226 } cpo_rcv_data;
227 
228 // This is the packet format to/from the Garmin USB
229 typedef struct __attribute__((__packed__))
230 {
231     uint8_t mPacketType;
232     uint8_t mReserved1;
233     uint16_t mReserved2;
234     uint16_t mPacketId;
235     uint16_t mReserved3;
236     uint32_t mDataSize;
237     union
238     {
239 	//int8_t chars[MAX_BUFFER_SIZE];
240 	// cppcheck-suppress unusedStructMember
241 	uint8_t uchars[MAX_BUFFER_SIZE];
242 	cpo_pvt_data pvt;
243 	cpo_sat_data sats;
244     } mData;
245 } Packet_t;
246 
247 // useful funcs to read/write ints
248 //  floats and doubles are Intel (little-endian) order only...
set_int16(uint8_t * buf,uint32_t value)249 static inline void set_int16(uint8_t * buf, uint32_t value)
250 {
251     buf[0] = (uint8_t) (0x0FF & value);
252     buf[1] = (uint8_t) (0x0FF & (value >> 8));
253 }
254 
set_int32(uint8_t * buf,uint32_t value)255 static inline void set_int32(uint8_t * buf, uint32_t value)
256 {
257     buf[0] = (uint8_t) (0x0FF & value);
258     buf[1] = (uint8_t) (0x0FF & (value >> 8));
259     buf[2] = (uint8_t) (0x0FF & (value >> 16));
260     buf[3] = (uint8_t) (0x0FF & (value >> 24));
261 }
262 
get_uint16(const uint8_t * buf)263 static inline uint16_t get_uint16(const uint8_t * buf)
264 {
265     return (uint16_t) (0xFF & buf[0])
266 	| ((uint16_t) (0xFF & buf[1]) << 8);
267 }
268 
269 #if defined(HAVE_LIBUSB) && defined(__linux__)
get_int32(const uint8_t * buf)270 static inline uint32_t get_int32(const uint8_t * buf)
271 {
272     return (uint32_t) (0xFF & buf[0])
273 	| ((uint32_t) (0xFF & buf[1]) << 8)
274 	| ((uint32_t) (0xFF & buf[2]) << 16)
275 	| ((uint32_t) (0xFF & buf[3]) << 24);
276 }
277 #endif /* HAVE_LIBUSB */
278 
279 // convert radians to degrees
radtodeg(double rad)280 static inline double radtodeg(double rad)
281 {
282     return (double)(rad * RAD_2_DEG);
283 }
284 
285 static gps_mask_t PrintSERPacket(struct gps_device_t *session,
286 				 unsigned char pkt_id, int pkt_len,
287 				 unsigned char *buf);
288 #if defined(HAVE_LIBUSB) && defined(__linux__)
289 static gps_mask_t PrintUSBPacket(struct gps_device_t *session,
290 				 Packet_t * pkt);
291 #endif /* HAVE_LIBUSB */
292 
PrintSERPacket(struct gps_device_t * session,unsigned char pkt_id,int pkt_len,unsigned char * buf)293 gps_mask_t PrintSERPacket(struct gps_device_t *session, unsigned char pkt_id,
294 			  int pkt_len, unsigned char *buf)
295 {
296 
297     gps_mask_t mask = ONLINE_SET;
298     int i = 0, j = 0;
299     uint16_t prod_id = 0;
300     uint16_t ver = 0;
301     int maj_ver;
302     int min_ver;
303     time_t time_l = 0;
304     char msg_buf[512] = "";
305     char *msg = NULL;
306     cpo_sat_data *sats = NULL;
307     cpo_pvt_data *pvt = NULL;
308     cpo_rcv_data *rmd = NULL;
309     double gps_tow = 0;
310 
311     GPSD_LOG(LOG_DATA, &session->context->errout,
312 	     "Garmin: PrintSERPacket(, %#02x, %#02x, )\n", pkt_id, pkt_len);
313 
314     session->cycle_end_reliable = true;
315 
316     switch (pkt_id) {
317     case ACK:
318 	GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: ACK\n");
319 	break;
320     case NAK:
321 	GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: NAK\n");
322 	break;
323     case GARMIN_PKTID_L001_COMMAND_DATA:
324 	prod_id = get_uint16((uint8_t *) buf);
325 	switch (prod_id) {
326 	case CMND_ABORT:
327 	    msg = "Abort current xfer";
328 	    break;
329 	case CMND_START_PVT_DATA:
330 	    msg = "Start Xmit PVT data";
331 	    break;
332 	case CMND_STOP_PVT_DATA:
333 	    msg = "Stop Xmit PVT data";
334 	    break;
335 	case CMND_START_RM_DATA:
336 	    msg = "Start RMD data";
337 	    break;
338 	default:
339 	    (void)snprintf(msg_buf, sizeof(msg_buf), "Unknown: %u",
340 			   (unsigned int)prod_id);
341 	    msg = msg_buf;
342 	    break;
343 	}
344 	GPSD_LOG(LOG_PROG, &session->context->errout,
345 		 "Garmin: Appl, Command Data: %s\n", msg);
346 	break;
347     case GARMIN_PKTID_PRODUCT_RQST:
348 	GPSD_LOG(LOG_PROG, &session->context->errout,
349 		 "Garmin: Appl, Product Data req\n");
350 	break;
351     case GARMIN_PKTID_PRODUCT_DATA:
352 	prod_id = get_uint16((uint8_t *) buf);
353 	ver = get_uint16((uint8_t *) & buf[2]);
354 	maj_ver = (int)(ver / 100);
355 	min_ver = (int)(ver - (maj_ver * 100));
356 	GPSD_LOG(LOG_PROG, &session->context->errout,
357 		 "Garmin: Appl, Product Data, sz: %d\n",
358 		 pkt_len);
359 	(void)snprintf(session->subtype, sizeof(session->subtype),
360 		       "%d: %d.%02d", (int)prod_id, maj_ver, min_ver);
361 	GPSD_LOG(LOG_INF, &session->context->errout,
362 		 "Garmin: Product ID: %d, SoftVer: %d.%02d\n",
363 		 prod_id, maj_ver, min_ver);
364 	GPSD_LOG(LOG_INF, &session->context->errout,
365 		 "Garmin: Product Desc: %s\n", &buf[4]);
366 	mask |= DEVICEID_SET;
367 	GPSD_LOG(LOG_DATA, &session->context->errout,
368 		 "Garmin: PRODUCT_DATA: subtype=%s\n",
369 		 session->subtype);
370 	break;
371     case GARMIN_PKTID_PVT_DATA:
372 	GPSD_LOG(LOG_PROG, &session->context->errout,
373 		 "Garmin: PVT Data (51) Sz: %d\n", pkt_len);
374 
375 	pvt = (cpo_pvt_data *) buf;
376 
377 	session->context->leap_seconds = (int)GPSD_LE16TOH(pvt->leap_sec);
378 	session->context->valid = LEAP_SECOND_VALID;
379 
380 	// 631065600, unix seconds for 31 Dec 1989 Zulu
381 	time_l = (time_t) (631065600 + (GPSD_LE32TOH(pvt->grmn_days) * 86400));
382 	// TODO, convert grmn_days to context->gps_week
383 	time_l -= session->context->leap_seconds;
384 
385 	// gps_tow is always like x.999 or x.998 just round it to nearest sec
386         // FIXME! this will break 5Hz garmins...
387 	gps_tow = GPSD_LED64(pvt->gps_tow);
388 	time_l += (time_t)round(gps_tow);
389 
390 	/* sanity check unix time against leap second.
391 	 * Leap second 18 at 1 Jan 2017: 1483228800 */
392 	if (17 < session->context->leap_seconds &&
393 	    1483228800L > time_l) {
394 	    time_l += 619315200;               // fast forward 1024 weeks
395         }
396 
397 	DTOTS(&session->context->gps_tow, gps_tow);
398 	session->newdata.time.tv_sec = time_l;
399 	session->newdata.time.tv_nsec = 0;
400         // (long long) for 32-bit systems
401 	GPSD_LOG(LOG_PROG, &session->context->errout,
402 		 "Garmin: time_l: %lld\n", (long long)time_l);
403 
404 	session->newdata.latitude = radtodeg(GPSD_LED64(pvt->lat));
405 	session->newdata.longitude = radtodeg(GPSD_LED64(pvt->lon));
406 	// altitude is WGS84
407 	session->newdata.altHAE = GPSD_LEF32(pvt->alt);
408 
409 	// geoid separation from WGS 84
410 	// gpsd sign is opposite of garmin sign
411 	session->newdata.geoid_sep = -GPSD_LEF32(pvt->msl_hght);
412 
413 	/* Estimated position error in meters.  Confidence (sigma) not
414          * specified by Garmin.
415 	 * We follow the advice at <http://gpsinformation.net/main/errors.htm>.
416          * Since GPS data is not gaussian, this is marginal advice...
417 	 * If this assumption changes here, it should also change in
418 	 * nmea_parse.c where we analyze PGRME.
419          */
420 	session->newdata.sep = GPSD_LEF32(pvt->epe) *
421                                    (GPSD_CONFIDENCE / CEP50_SIGMA);
422         /* eph, horizaontal error, 2 sigma */
423 	session->newdata.eph = GPSD_LEF32(pvt->eph) *
424                                    (GPSD_CONFIDENCE / CEP50_SIGMA);
425         /* eph, horizaontal error, 2 sigma */
426 	session->newdata.epv = GPSD_LEF32(pvt->epv) *
427                                    (GPSD_CONFIDENCE / CEP50_SIGMA);
428 
429 	/* meters/sec */
430 	session->newdata.NED.velN = GPSD_LEF32(pvt->lat_vel);
431 	session->newdata.NED.velE = GPSD_LEF32(pvt->lon_vel);
432 	session->newdata.NED.velD = -GPSD_LEF32(pvt->alt_vel);
433 
434 	switch (GPSD_LE16TOH(pvt->fix)) {
435 	case 0:
436 	case 1:
437 	default:
438 	    // no fix
439 	    session->gpsdata.status = STATUS_NO_FIX;
440 	    session->newdata.mode = MODE_NO_FIX;
441 	    break;
442 	case 2:
443 	    // 2D fix
444 	    session->gpsdata.status = STATUS_FIX;
445 	    session->newdata.mode = MODE_2D;
446 	    break;
447 	case 3:
448 	    // 3D fix
449 	    session->gpsdata.status = STATUS_FIX;
450 	    session->newdata.mode = MODE_3D;
451 	    break;
452 	case 4:
453 	    // 2D Differential fix
454 	    session->gpsdata.status = STATUS_DGPS_FIX;
455 	    session->newdata.mode = MODE_2D;
456 	    break;
457 	case 5:
458 	    // 3D differential fix
459 	    session->gpsdata.status = STATUS_DGPS_FIX;
460 	    session->newdata.mode = MODE_3D;
461 	    break;
462 	}
463 
464 	GPSD_LOG(LOG_PROG, &session->context->errout,
465 		 "Garmin: Appl, mode %d, status %d\n",
466 		 session->newdata.mode, session->gpsdata.status);
467 
468         /* save some expensive calculations if not needed */
469         if (session->context->errout.debug >= LOG_INF) {
470 
471 	    GPSD_LOG(LOG_INF, &session->context->errout,
472 		     "Garmin: UTC Time: %lld\n",
473 		     (long long)session->newdata.time.tv_sec);
474 	    GPSD_LOG(LOG_INF, &session->context->errout,
475 		     "Garmin: Geoid Separation (MSL-WGS84): from garmin %lf, "
476                      "calculated %lf\n",
477                      session->newdata.geoid_sep,
478 		     wgs84_separation(session->newdata.latitude,
479 					 session->newdata.longitude));
480 
481 	    GPSD_LOG(LOG_INF, &session->context->errout,
482 		     "Garmin: Alt: %.3f, sep: %.3f, eph: %.3f, Epv: %.3f, "
483                      "Fix: %d, Gps_tow: %f, Lat: %.3f, Lon: %.3f, "
484                      "velN: %.3f, velE: %.3f, velD: %.3f, geoidsep: %.3f, "
485                      "Leap: %d, GarminDays: %d\n",
486                      session->newdata.altHAE,
487                      session->newdata.sep,
488                      session->newdata.eph,
489                      session->newdata.epv,
490                      GPSD_LE16TOH(pvt->fix),
491 		     gps_tow,
492                      session->newdata.latitude,
493 		     session->newdata.longitude,
494                      session->newdata.NED.velN,
495                      session->newdata.NED.velE,
496                      session->newdata.NED.velD,
497                      session->newdata.geoid_sep,
498                      session->context->leap_seconds,
499 		     GPSD_LE32TOH(pvt->grmn_days));
500         }
501 
502 	if (session->newdata.mode > MODE_NO_FIX) {
503 	    /* data only valid with a fix */
504 	    mask |=
505 		TIME_SET | LATLON_SET | ALTITUDE_SET | STATUS_SET | MODE_SET |
506 		HERR_SET | PERR_IS | CLEAR_IS | REPORT_IS | VNED_SET;
507 	    /*
508 	     * Garmin documentation says we should wait until four good fixes
509 	     * have been seen before trying to use the device for precision
510 	     * time service.
511 	     */
512 	    if (session->fixcnt > 3)
513 		mask |= NTPTIME_IS;
514 	}
515 	GPSD_LOG(LOG_DATA, &session->context->errout,
516 		 "Garmin: PVT_DATA: time=%lld, lat=%.2f lon=%.2f "
517 		 "eph=%.2f sep=%.2f epv=%.2f  mode=%d status=%d\n",
518 		 (long long)session->newdata.time.tv_sec,
519 		 session->newdata.latitude,
520 		 session->newdata.longitude,
521 		 session->newdata.eph,
522 		 session->newdata.sep,
523 		 session->newdata.epv,
524 		 session->newdata.mode,
525 		 session->gpsdata.status);
526 	break;
527     case GARMIN_PKTID_RMD_DATA:
528     case GARMIN_PKTID_RMD41_DATA:
529 	rmd = (cpo_rcv_data *) buf;
530 	GPSD_LOG(LOG_DATA, &session->context->errout,
531 		 "Garmin: PVT RMD Data Sz: %d\n", pkt_len);
532 	GPSD_LOG(LOG_PROG, &session->context->errout,
533 		 "Garmin: PVT RMD rcvr_tow: %f, rcvr_wn: %d\n",
534 		 GPSD_LED64(rmd->rcvr_tow), GPSD_LE16TOH(rmd->rcvr_wn));
535 	for (i = 0; i < GARMIN_CHANNELS; i++) {
536 	    GPSD_LOG(LOG_INF, &session->context->errout,
537 		     "Garmin: PVT RMD Sat: %3u, cycles: %9u, pr: %16.6f, "
538 		     "phase: %7.3f, slp_dtct: %3s, snr: %3u, Valid: %3s\n",
539 		     (int)rmd->sv[i].svid + 1,
540 		     GPSD_LE32TOH(rmd->sv[i].cycles),
541 		     GPSD_LED64(rmd->sv[i].pr),
542 		     (GPSD_LE16TOH(rmd->sv[i].phase) * 360.0) / 2048.0,
543 		     rmd->sv[i].slp_dtct != 0 ? "Yes" : "No",
544 		     rmd->sv[i].snr_dbhz,
545 		     rmd->sv[i].valid != 0 ? "Yes" : "No");
546 	}
547 	break;
548 
549     case GARMIN_PKTID_SAT_DATA:
550         // record ID 0x72 (114)
551 	GPSD_LOG(LOG_PROG, &session->context->errout,
552 		 "Garmin: SAT Data Sz: %d\n", pkt_len);
553 	sats = (cpo_sat_data *) buf;
554 
555 	session->gpsdata.satellites_used = 0;
556 	gpsd_zero_satellites(&session->gpsdata);
557 	for (i = 0, j = 0; i < GARMIN_CHANNELS; i++, sats++) {
558 	    GPSD_LOG(LOG_INF, &session->context->errout,
559 		     "Garmin: Sat %2d, snr: %5u, elev: %2d, Azmth: %3d, "
560                      "Stat: x%x\n",
561 		     sats->svid, GPSD_LE16TOH(sats->snr), sats->elev,
562 		     GPSD_LE16TOH(sats->azmth),
563 		     sats->status);
564 
565 	    if (255 == (int)sats->svid) {
566 		// Garmin uses 255 for empty
567 		// gpsd uses 0 for empty
568 		continue;
569 	    }
570 
571 	    if ((int)sats->svid <= 32) {
572                 /* GPS 1-32 */
573 		session->gpsdata.skyview[j].PRN = (short)sats->svid;
574 		session->gpsdata.skyview[j].svid = (short)sats->svid;
575 		session->gpsdata.skyview[j].gnssid = GNSSID_GPS;
576 	    } else {
577                 /* SBAS 33-64 */
578 		session->gpsdata.skyview[j].PRN = (short)sats->svid;
579 		session->gpsdata.skyview[j].svid = (short)sats->svid + 87;
580 		session->gpsdata.skyview[j].gnssid = GNSSID_SBAS;
581             }
582 	    session->gpsdata.skyview[j].azimuth =
583                 (short)GPSD_LE16TOH(sats->azmth);
584 	    session->gpsdata.skyview[j].elevation = (short)sats->elev;
585             if (0xffff == sats->snr) {
586                 session->gpsdata.skyview[j].ss = NAN;
587             } else {
588                 // Garmin does not document this.  snr is in dB*100
589                 // Known, but not seen satellites have a dB value of -1*100
590                 session->gpsdata.skyview[j].ss =
591                     (float)(GPSD_LE16TOH(sats->snr) / 100.0);
592 	    }
593 	    // FIX-ME: Garmin documents this, but Daniel Dorau
594 	    // <daniel.dorau@gmx.de> says the behavior on his GPSMap60CSX
595 	    // doesn't match it.
596 	    if ((uint8_t) 0 != (sats->status & 4)) {
597 		// used in solution?
598 		session->gpsdata.skyview[j].used = true;
599 		session->gpsdata.satellites_used++;
600 	    }
601 	    session->gpsdata.satellites_visible++;
602 	    j++;
603 
604 	}
605 	session->gpsdata.skyview_time.tv_sec = 0;
606 	session->gpsdata.skyview_time.tv_nsec = 0;
607         mask |= USED_IS | SATELLITE_SET;
608 	GPSD_LOG(LOG_DATA, &session->context->errout,
609 		 "Garmin: SAT_DATA: visible=%d used=%d\n",
610 		 session->gpsdata.satellites_visible,
611 		 session->gpsdata.satellites_used);
612 	break;
613     case GARMIN_PKTID_PROTOCOL_ARRAY:
614         // Pid_Protocol_Array, ID 253
615 	// this packet is never requested, it just comes, in some case
616 	// after a GARMIN_PKTID_PRODUCT_RQST
617 	GPSD_LOG(LOG_INF, &session->context->errout,
618 		 "Garmin: Appl, Product Capability, sz: %d\n",
619 		 pkt_len);
620 	for (i = 0; i < pkt_len; i += 3) {
621 	    GPSD_LOG(LOG_INF, &session->context->errout,
622 		     "Garmin:   %c%03d\n",
623 		     buf[i],	get_uint16((uint8_t *) & buf[i + 1]));
624 	}
625 	break;
626     default:
627 	GPSD_LOG(LOG_WARN, &session->context->errout,
628 		 "Garmin: Unknown packet id: %#02x, Sz: %#02x\n",
629 		 pkt_id, pkt_len);
630 	break;
631     }
632     GPSD_LOG(LOG_DATA, &session->context->errout,
633 	     "Garmin: PrintSERPacket(, %#02x, %#02x, ) mask=(%s)\n",
634 	     pkt_id, pkt_len, gps_maskdump(mask));
635     return mask;
636 }
637 
638 
639 #if defined(HAVE_LIBUSB) && defined(__linux__)
640 // This works around cppcheck not looking into enough config branches
641 // cppcheck-suppress unusedFunction
PrintUSBPacket(struct gps_device_t * session,Packet_t * pkt)642 static gps_mask_t PrintUSBPacket(struct gps_device_t *session, Packet_t * pkt)
643 /* For debugging, decodes and prints some known packets */
644 {
645     gps_mask_t mask = 0;
646     int maj_ver;
647     int min_ver;
648     uint32_t mode = 0;
649     uint16_t prod_id = 0;
650     uint32_t veri = 0;
651     uint32_t serial;
652     uint32_t mDataSize = get_int32((uint8_t *) & pkt->mDataSize);
653     uint8_t *buffer = (uint8_t *) pkt;
654 
655     GPSD_LOG(LOG_PROG, &session->context->errout, "Garmin: PrintUSBPacket()\n");
656     if (DLE == pkt->mPacketType) {
657 	GPSD_LOG(LOG_PROG, &session->context->errout,
658 		 "Garmin: really a SER packet!\n");
659 	return PrintSERPacket(session,
660 			      (unsigned char)buffer[1],
661 			      (int)buffer[2], (unsigned char *)(buffer + 3));
662     }
663 
664     if (4096 < mDataSize) {
665 	GPSD_LOG(LOG_WARN, &session->context->errout,
666 		 "Garmin: bogus packet, size too large=%d\n",
667 		 mDataSize);
668 	return 0;
669     }
670 
671     switch (pkt->mPacketType) {
672     case GARMIN_LAYERID_TRANSPORT:
673 	/* Garmin USB layer specific */
674 	switch (pkt->mPacketId) {
675 	case GARMIN_PKTID_TRANSPORT_START_SESSION_REQ:
676             // Pid_Start_Session, ID 5
677 	    GPSD_LOG(LOG_PROG, &session->context->errout,
678 		     "Garmin: Transport, Start Session req\n");
679 	    break;
680 	case GARMIN_PKTID_TRANSPORT_START_SESSION_RESP:
681             // Pid_Session_Started, ID 6
682 	    mode = get_int32(&pkt->mData.uchars[0]);
683 	    GPSD_LOG(LOG_PROG, &session->context->errout,
684 		     "Garmin: Transport, Start Session resp, unit: 0x%x\n",
685 		     mode);
686 	    break;
687 	default:
688 	    GPSD_LOG(LOG_PROG, &session->context->errout,
689 		     "Garmin: Transport, Packet: Type %d %d %d, ID: %d,"
690                      "Sz: %d\n",
691 		     pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
692 		     pkt->mPacketId, mDataSize);
693 	    break;
694 	}
695 	break;
696     case GARMIN_LAYERID_APPL:
697 	/* raw data transport, shared with Garmin Serial Driver */
698 
699 	mask = PrintSERPacket(session,
700 			      (unsigned char)pkt->mPacketId,
701 			      (int)mDataSize,
702 			      (unsigned char *)pkt->mData.uchars);
703 	break;
704     case 75:
705 	// private, garmin USB kernel driver specific
706 	switch (pkt->mPacketId) {
707 	case PRIV_PKTID_SET_MODE:
708 	    prod_id = get_uint16(&pkt->mData.uchars[0]);
709 	    GPSD_LOG(LOG_PROG, &session->context->errout,
710 		     "Garmin: Private, Set Mode: %d\n", prod_id);
711 	    break;
712 	case PRIV_PKTID_INFO_REQ:
713 	    GPSD_LOG(LOG_PROG, &session->context->errout,
714 		     "Garmin: Private, ID: Info Req\n");
715 	    break;
716 	case PRIV_PKTID_INFO_RESP:
717 	    veri = get_int32(pkt->mData.uchars);
718 	    maj_ver = (int)(veri >> 16);
719 	    min_ver = (int)(veri & 0xffff);
720 	    mode = get_int32(&pkt->mData.uchars[4]);
721 	    serial = get_int32(&pkt->mData.uchars[8]);
722 	    GPSD_LOG(LOG_PROG, &session->context->errout,
723 		     "Garmin: Private, ID: Info Resp\n");
724 	    GPSD_LOG(LOG_INF, &session->context->errout,
725 		     "Garmin: USB Driver found, Version %d.%d, Mode: %d, GPS Serial# %u\n",
726 		     maj_ver, min_ver, mode, serial);
727 	    break;
728 	default:
729 	    GPSD_LOG(LOG_PROG, &session->context->errout,
730 		     "Garmin: Private, Packet: ID: %d, Sz: %d\n",
731 		     pkt->mPacketId, mDataSize);
732 	    break;
733 	}
734 	break;
735     default:
736 	GPSD_LOG(LOG_PROG, &session->context->errout,
737 		 "Garmin: Packet: Type %d %d %d, ID: %d, Sz: %d\n",
738 		 pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
739 		 pkt->mPacketId, mDataSize);
740 	break;
741     }
742 
743     return mask;
744 }
745 
746 #endif /* HAVE_LIBUSB */
747 
748 
749 #if defined(HAVE_LIBUSB) && defined(__linux__)
750 /* build and send a packet w/ USB protocol */
Build_Send_USB_Packet(struct gps_device_t * session,uint32_t layer_id,uint32_t pkt_id,uint32_t length,uint32_t data)751 static void Build_Send_USB_Packet(struct gps_device_t *session,
752 				  uint32_t layer_id, uint32_t pkt_id,
753 				  uint32_t length, uint32_t data)
754 {
755     uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
756     Packet_t *thePacket = (Packet_t *) buffer;
757     ssize_t theBytesReturned = 0;
758     ssize_t theBytesToWrite = 12 + (ssize_t) length;
759 
760     set_int32(buffer, layer_id);
761     set_int32(buffer + 4, pkt_id);
762     set_int32(buffer + 8, length);
763     if (2 == length) {
764 	set_int16(buffer + 12, data);
765     } else if (4 == length) {
766 	set_int32(buffer + 12, data);
767     }
768     (void)PrintUSBPacket(session, thePacket);
769 
770     theBytesReturned = gpsd_write(session, (const char *)thePacket,
771 				  (size_t) theBytesToWrite);
772     GPSD_LOG(LOG_PROG, &session->context->errout,
773 	     "Garmin: SendPacket(), wrote %zd bytes\n",
774 	     theBytesReturned);
775 
776     // Garmin says:
777     // If the packet size was an exact multiple of the USB packet
778     // size, we must make a final write call with no data
779 
780     // as a practical matter no known packets are 64 bytes long so
781     // this is untested
782 
783     // So here goes just in case
784     if (0 == (theBytesToWrite % ASYNC_DATA_SIZE)) {
785 	char *n = "";
786 	(void)gpsd_write(session, n, 0);
787     }
788 }
789 #endif /* HAVE_LIBUSB && __linux__ */
790 
791 /* build and send a packet in serial protocol */
792 /* layer_id unused */
793 // FIX-ME: This should go through the common message buffer someday
Build_Send_SER_Packet(struct gps_device_t * session,uint32_t layer_id UNUSED,uint32_t pkt_id,uint32_t length,uint32_t data)794 static void Build_Send_SER_Packet(struct gps_device_t *session,
795 				  uint32_t layer_id UNUSED, uint32_t pkt_id,
796 				  uint32_t length, uint32_t data)
797 {
798     uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
799     uint8_t *buffer0 = buffer;
800     Packet_t *thePacket = (Packet_t *) buffer;
801     ssize_t theBytesReturned = 0;
802     ssize_t theBytesToWrite = 6 + (ssize_t) length;
803     uint8_t chksum = 0;
804 
805     *buffer++ = (uint8_t) DLE;
806     *buffer++ = (uint8_t) pkt_id;
807     chksum = pkt_id;
808     *buffer++ = (uint8_t) length;
809     chksum += length;
810     /* ??? What is this doing? */
811     if (2 == length) {
812 	/* carefull!  no DLE stuffing here! */
813 	set_int16(buffer, data);
814 	chksum += buffer[0];
815 	chksum += buffer[1];
816     } else if (4 == length) {
817 	/* carefull!  no DLE stuffing here! */
818 	set_int32(buffer, data);
819 	chksum += buffer[0];
820 	chksum += buffer[1];
821 	chksum += buffer[2];
822 	chksum += buffer[3];
823     }
824     /* ??? How is data copied to the buffer? */
825     buffer += length;
826 
827     // Add checksum
828     *buffer++ = -chksum;
829     if (DLE == -chksum) {
830 	/* stuff another DLE */
831 	*buffer++ = (uint8_t) DLE;
832 	theBytesToWrite++;
833     }
834     // Add DLE, ETX
835     *buffer++ = (uint8_t) DLE;
836     /* we used to say n++ here, but scan-build complains */
837     *buffer = (uint8_t) ETX;
838 
839     (void)PrintSERPacket(session,
840 			 (unsigned char)buffer0[1],
841 			 (int)buffer0[2], (unsigned char *)(buffer0 + 3));
842 
843     theBytesReturned = gpsd_write(session, (const char *)thePacket,
844 				  (size_t) theBytesToWrite);
845     GPSD_LOG(LOG_PROG, &session->context->errout,
846 	     "Garmin: SendPacket(), wrote %zd bytes\n",
847 	     theBytesReturned);
848 
849 }
850 
851 #if defined(HAVE_LIBUSB) && defined(__linux__)
852 /*
853  * is_usb_device() - is a specified device USB matching given vendor/product?
854  *
855  * BUG: Doesn't actually match against path yet. Must finish this function
856  * by querying /sys/dev/char, either directly or using libudev. Greg KH
857  * assures this is possible, though he is vague about how.
858  *
859  * libudev: http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/
860  */
861 // This works around cppcheck not looking into enough config branches
862 // cppcheck-suppress unusedFunction
is_usb_device(const char * path UNUSED,int vendor,int product,struct gpsd_errout_t * errout)863 static bool is_usb_device(const char *path UNUSED, int vendor, int product,
864 			  struct gpsd_errout_t *errout)
865 {
866     // discover devices
867     libusb_device **list;
868     ssize_t cnt;
869     ssize_t i = 0;
870     bool found = false;
871 
872     GPSD_LOG(LOG_INF, errout, "attempting USB device enumeration.\n");
873     (void)libusb_init(NULL);
874 
875     if ((cnt = libusb_get_device_list(NULL, &list)) < 0) {
876 	GPSD_LOG(LOG_ERROR, errout, "USB device list call failed.\n");
877 	libusb_exit(NULL);
878 	return false;
879     }
880 
881     for (i = 0; i < cnt; i++) {
882 	struct libusb_device_descriptor desc;
883 	libusb_device *dev = list[i];
884 
885 	int r = libusb_get_device_descriptor(dev, &desc);
886 	if (r < 0) {
887 	    GPSD_LOG(LOG_ERROR, errout,
888 		     "USB descriptor fetch failed on device %zd.\n", i);
889 	    continue;
890 	}
891 
892 	/* we can extract device descriptor data */
893 	GPSD_LOG(LOG_INF, errout,
894 		 "%04x:%04x (bus %d, device %d)\n",
895 		 desc.idVendor, desc.idProduct,
896 		 libusb_get_bus_number(dev),
897 		 libusb_get_device_address(dev));
898 
899 	/* we match if vendor and product ID are right */
900 	if (desc.idVendor == (uint16_t)vendor && desc.idProduct == (uint16_t)product) {
901 	    found = true;
902 	    break;
903 	}
904     }
905 
906     GPSD_LOG(LOG_INF, errout,
907 	     "vendor/product match with %04x:%04x %sfound\n",
908 	     vendor, product, found ? "" : "not ");
909     libusb_free_device_list(list, 1);
910     libusb_exit(NULL);
911     return found;
912 }
913 
914 #endif /* HAVE_LIBUSB */
915 
916 /*
917  * garmin_usb_detect() - detect a Garmin USB device connected to session fd.
918  *
919  * This is ONLY for USB devices reporting as: 091e:0003.
920  *
921  * This driver ONLY works in Linux and ONLY when the garmin_gps kernel
922  * module is installed.
923  *
924  * This is only necessary because under Linux Garmin USB devices need a
925  * kernel module rather than being normal USB-serial devices.
926  *
927  * The actual wire protocol from the Garmin device is very strange. There
928  * are no delimiters.  End of packet is signaled by a zero-length read
929  * on the USB device, and start of packet is the next read.  You can't just
930  * ignore the zero reads and pass the data through - you'd never be able
931  * to tell where the packet boundaries are.
932  *
933  * The garmin_usb module's job is to grab the packet and frame it in
934  * DLEs (with DLE stuffing).  This makes the USB packets look as
935  * though they came from a regular Garmin *serial* device, which is how
936  * most of the processing for both types can be unified here.
937  *
938  * return 1 is device found
939  * return 0 if not
940  */
garmin_usb_detect(struct gps_device_t * session UNUSED)941 static bool garmin_usb_detect(struct gps_device_t *session UNUSED)
942 {
943 #if defined(__linux__)
944     /*
945      * Only perform this check if we're looking at a USB-serial
946      * device.  This prevents drivers for attached serial GPSes
947      * fronm being rudely elbowed aside by this one if they happen
948      * to be trying to coexist with the Garmin.
949      */
950     if (session->sourcetype != source_usb)
951 	return false;
952     else {
953 #ifdef HAVE_LIBUSB
954 	if (!is_usb_device(session->gpsdata.dev.path, 0x091e, 0x0003,
955 		&session->context->errout))
956 	    return false;
957 
958 	if (!gpsd_set_raw(session)) {
959 	    GPSD_LOG(LOG_ERROR, &session->context->errout,
960 		     "Garmin: garmin_usb_detect: error changing port attributes: %s\n",
961 		     strerror(errno));
962 	    return false;
963 	}
964 
965 	if (sizeof(session->driver.garmin.Buffer) < sizeof(Packet_t)) {
966 	    /* dunno how this happens, but it does on some compilers */
967 	    GPSD_LOG(LOG_ERROR, &session->context->errout,
968 		     "Garmin: garmin_usb_detect: Compile error, garmin.Buffer too small.\n");
969 	    return false;
970 	}
971 
972 	// FIXME!!! needs to use libusb totally and move garmin_gps aside */
973 	// set Mode 1, mode 0 is broken somewhere past 2.6.14
974 	// but how?
975 	GPSD_LOG(LOG_PROG, &session->context->errout,
976 		 "Garmin: Set garmin_gps driver mode = 0\n");
977 	Build_Send_USB_Packet(session, GARMIN_LAYERID_PRIVATE,
978 			      PRIV_PKTID_SET_MODE, 4, MODE_GARMIN_SERIAL);
979 	// expect no return packet !?
980 
981 	return true;
982 #else
983 	return false;
984 #endif /* HAVE_LIBUSB */
985     }
986 #else
987     return false;
988 #endif /* __linux__ */
989 }
990 
garmin_event_hook(struct gps_device_t * session,event_t event)991 static void garmin_event_hook(struct gps_device_t *session, event_t event)
992 {
993     if (session->context->readonly)
994 	return;
995     /*
996      * FIX-ME: It might not be necessary to call this on reactivate.
997      * Experiment to see if the holds its settings through a close.
998      */
999     if (event == event_identified || event == event_reactivate) {
1000 	// Tell the device to send product data
1001 	GPSD_LOG(LOG_PROG, &session->context->errout,
1002 		 "Garmin: Get Product Data\n");
1003 	Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1004 			      GARMIN_PKTID_PRODUCT_RQST, 0, 0);
1005 
1006 	// turn on PVT data 49
1007 	GPSD_LOG(LOG_PROG, &session->context->errout,
1008 		 "Garmin: Set to send reports every 1 second\n");
1009 
1010 	Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1011 			      GARMIN_PKTID_L001_COMMAND_DATA, 2,
1012 			      CMND_START_PVT_DATA);
1013 
1014 #if USE_RMD
1015 	// turn on RMD data 110
1016 	GPSD_LOG(LOG_PROG, &session->context->errout,
1017 		 "Garmin: Set to send Raw sat data\n");
1018 	Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1019 			      GARMIN_PKTID_L001_COMMAND_DATA, 2,
1020 			      CMND_START_RM_DATA);
1021 #endif
1022     }
1023     if (event == event_deactivate)
1024 	/* FIX-ME: is any action needed, or is closing the port sufficient? */
1025 	GPSD_LOG(LOG_PROG, &session->context->errout,
1026 		 "Garmin: garmin_close()\n");
1027 }
1028 
1029 #define Send_ACK()    Build_Send_SER_Packet(session, 0, ACK, 0, 0)
1030 #define Send_NAK()    Build_Send_SER_Packet(session, 0, NAK, 0, 0)
1031 
garmin_ser_parse(struct gps_device_t * session)1032 gps_mask_t garmin_ser_parse(struct gps_device_t *session)
1033 {
1034     unsigned char *buf = session->lexer.outbuffer;
1035     size_t len = session->lexer.outbuflen;
1036     unsigned char data_buf[MAX_BUFFER_SIZE];
1037     unsigned char c;
1038     int i = 0;
1039     size_t n = 0;
1040     int data_index = 0;
1041     int got_dle = 0;
1042     unsigned char pkt_id = 0;
1043     unsigned char pkt_len = 0;
1044     unsigned char chksum = 0;
1045     gps_mask_t mask = 0;
1046     struct timespec delay;
1047 
1048     GPSD_LOG(LOG_RAW, &session->context->errout,
1049              "Garmin: garmin_ser_parse()\n");
1050     if (6 > len) {
1051 	/* WTF? */
1052 	/* minimum packet; <DLE> [pkt id] [length=0] [chksum] <DLE> <STX> */
1053 	Send_NAK();
1054 	GPSD_LOG(LOG_RAW, &session->context->errout,
1055 		 "Garmin: serial too short: %zd\n", len);
1056 	return 0;
1057     }
1058     /* debug */
1059     for (i = 0; i < (int)len; i++) {
1060 	GPSD_LOG(LOG_RAW, &session->context->errout,
1061 		 "Garmin: Char: %#02x\n", buf[i]);
1062     }
1063 
1064     if ('\x10' != buf[0]) {
1065 	Send_NAK();
1066 	GPSD_LOG(LOG_RAW, &session->context->errout,
1067 		 "Garmin: buf[0] not DLE\n");
1068 	return 0;
1069     }
1070     n = 1;
1071     pkt_id = buf[n++];
1072     chksum = pkt_id;
1073     if ('\x10' == pkt_id) {
1074 	if ('\x10' != buf[n++]) {
1075 	    Send_NAK();
1076 	    GPSD_LOG(LOG_RAW, &session->context->errout,
1077 		     "Garmin: Bad pkt_id %#02x\n", pkt_id);
1078 	    return 0;
1079 	}
1080     }
1081 
1082     pkt_len = buf[n++];
1083     chksum += pkt_len;
1084     if ('\x10' == pkt_len) {
1085 	if ('\x10' != buf[n++]) {
1086 	    GPSD_LOG(LOG_RAW, &session->context->errout,
1087 		     "Garmin: Bad pkt_len %#02x\n", pkt_len);
1088 	    Send_NAK();
1089 	    return 0;
1090 	}
1091     }
1092     data_index = 0;
1093     for (i = 0; i < 256; i++) {
1094 
1095 	if ((int)pkt_len == data_index) {
1096 	    // got it all
1097 	    break;
1098 	}
1099 	if (len < n + i) {
1100 	    GPSD_LOG(LOG_RAW, &session->context->errout,
1101 		     "Garmin: Packet too short %zd < %zd\n",
1102 		     len, n + i);
1103 	    Send_NAK();
1104 	    return 0;
1105 	}
1106 	c = buf[n + i];
1107 	if (got_dle) {
1108 	    got_dle = 0;
1109 	    if ('\x10' != c) {
1110 		Send_NAK();
1111 		GPSD_LOG(LOG_RAW, &session->context->errout,
1112 			 "Garmin: Bad DLE %#02x\n", c);
1113 		return 0;
1114 	    }
1115 	} else {
1116 	    chksum += c;
1117 	    data_buf[data_index++] = c;
1118 	    if ('\x10' == c) {
1119 		got_dle = 1;
1120 	    }
1121 	}
1122     }
1123     /* get checksum */
1124     if (len < n + i) {
1125 	Send_NAK();
1126 	GPSD_LOG(LOG_RAW, &session->context->errout,
1127 		 "Garmin: No checksum, Packet too short %zd < %zd\n", len,
1128 		 n + i);
1129 	return 0;
1130     }
1131     c = buf[n + i++];
1132     chksum += c;
1133     /* get final DLE */
1134     if (len < n + i) {
1135 	Send_NAK();
1136 	GPSD_LOG(LOG_RAW, &session->context->errout,
1137 		 "Garmin: No final DLE, Packet too short %zd < %zd\n", len,
1138 		 n + i);
1139 	return 0;
1140     }
1141     c = buf[n + i++];
1142     if ('\x10' != c) {
1143 	Send_NAK();
1144 	GPSD_LOG(LOG_RAW, &session->context->errout,
1145 		 "Garmin: Final DLE not DLE\n");
1146 	return 0;
1147     }
1148     /* get final ETX */
1149     if (len < n + i) {
1150 	Send_NAK();
1151 	GPSD_LOG(LOG_RAW, &session->context->errout,
1152 		 "Garmin: No final ETX, Packet too short %zd < %zd\n", len,
1153 		 n + i);
1154 	return 0;
1155     }
1156     /* we used to say n++ here, but scan-build complains */
1157     c = buf[n + i];
1158     if ('\x03' != c) {
1159 	Send_NAK();
1160 	GPSD_LOG(LOG_RAW, &session->context->errout,
1161 		 "Garmin: Final ETX not ETX\n");
1162 	return 0;
1163     }
1164 
1165     /* debug */
1166     for (i = 0; i < data_index; i++) {
1167 	GPSD_LOG(LOG_RAW, &session->context->errout,
1168 		 "Garmin: Char: %#02x\n", data_buf[i]);
1169     }
1170 
1171 
1172     GPSD_LOG(LOG_DATA, &session->context->errout,
1173 	     "Garmin: garmin_ser_parse() Type: %#02x, Len: %#02x, chksum: %#02x\n",
1174 	     pkt_id, pkt_len, chksum);
1175     mask = PrintSERPacket(session, pkt_id, pkt_len, data_buf);
1176 
1177     // sending ACK too soon might hang the session
1178     // so send ACK last, after a pause
1179     /* wait 300 uSec */
1180     delay.tv_sec = 0;
1181     delay.tv_nsec = 300000L;
1182     nanosleep(&delay, NULL);
1183 
1184     Send_ACK();
1185     GPSD_LOG(LOG_DATA, &session->context->errout,
1186 	     "Garmin: garmin_ser_parse( )\n");
1187     return mask;
1188 }
1189 
1190 
1191 #ifdef RECONFIGURE_ENABLE
settle(void)1192 static void settle(void)
1193 {
1194     struct timespec delay, rem;
1195     memset(&delay, 0, sizeof(delay));
1196     delay.tv_sec = 0;
1197     delay.tv_nsec = 333000000L;
1198     nanosleep(&delay, &rem);
1199 }
1200 
garmin_switcher(struct gps_device_t * session,int mode)1201 static void garmin_switcher(struct gps_device_t *session, int mode)
1202 {
1203     if (mode == MODE_NMEA) {
1204 	const unsigned  char switcher[] =
1205 	    { 0x10, 0x0A, 0x02, 0x26, 0x00, 0xCE, 0x10, 0x03 };
1206 	// Note hard-coded string length in the next line...
1207 	ssize_t status = gpsd_write(session, (char *)switcher,
1208                                     sizeof(switcher));
1209 	if (status == (ssize_t)sizeof(switcher)) {
1210 	    GPSD_LOG(LOG_PROG, &session->context->errout,
1211 		     "Garmin: => GPS: turn off binary %02x %02x %02x... \n",
1212 		     switcher[0], switcher[1], switcher[2]);
1213 	} else {
1214 	    GPSD_LOG(LOG_ERROR, &session->context->errout,
1215 		     "Garmin: => GPS: FAILED\n");
1216 	}
1217 	settle();		// wait 333mS, essential!
1218 
1219 	/* once a sec, no binary, no averaging, NMEA 2.3, WAAS */
1220 	(void)nmea_send(session, "$PGRMC1,1,1");
1221 	//(void)nmea_send(fd, "$PGRMC1,1,1,1,,,,2,W,N");
1222 	(void)nmea_send(session, "$PGRMI,,,,,,,R");
1223 	settle();		// wait 333mS, essential!
1224     } else {
1225 	(void)nmea_send(session, "$PGRMC1,1,2,1,,,,2,W,N");
1226 	(void)nmea_send(session, "$PGRMI,,,,,,,R");
1227 	settle();		// wait 333mS, essential!
1228     }
1229 }
1230 #endif /* RECONFIGURE_ENABLE */
1231 
1232 #ifdef CONTROLSEND_ENABLE
garmin_control_send(struct gps_device_t * session,char * buf,size_t buflen)1233 static ssize_t garmin_control_send(struct gps_device_t *session,
1234 				   char *buf, size_t buflen)
1235 /* not used by the daemon, it's for gpsctl and friends */
1236 {
1237     session->msgbuflen = buflen;
1238     (void)memcpy(session->msgbuf, buf, buflen);
1239     return gpsd_write(session, session->msgbuf, session->msgbuflen);
1240 }
1241 #endif /* CONTROLSEND_ENABLE */
1242 
garmin_time_offset(struct gps_device_t * session)1243 static double garmin_time_offset(struct gps_device_t *session)
1244 {
1245     if (session->sourcetype == source_usb) {
1246 	return 0.035;		/* Garmin USB, expect +/- 40mS jitter */
1247     }
1248     /* only two sentences ships time */
1249     /* but the PVT data is always first */
1250     switch (session->gpsdata.dev.baudrate) {
1251     case 4800:
1252 	return 0.430;		/* TBD */
1253     case 9600:
1254 	return 0.430;		/* tested 12Arp10 */
1255     case 19200:
1256 	return 0.430;		/* TBD */
1257     case 38400:
1258 	return 0.430;		/* TBD */
1259     }
1260     return 0.430;		/* WTF?  WAG */
1261 }
1262 
1263 /* this is everything we export */
1264 
1265 /* *INDENT-OFF* */
1266 const struct gps_type_t driver_garmin_usb_binary =
1267 {
1268     .type_name      = "Garmin USB binary",	/* full name of type */
1269     .packet_type    = GARMIN_PACKET,	/* associated lexer packet type */
1270     .flags	    = DRIVER_STICKY,	/* remember this */
1271     .trigger        = NULL,		/* no trigger, it has a probe */
1272     .channels       = GARMIN_CHANNELS,	/* consumer-grade GPS */
1273     .probe_detect   = garmin_usb_detect,/* how to detect at startup time */
1274     .get_packet     = generic_get,      /* how to grab a packet */
1275     .parse_packet   = garmin_ser_parse,	/* parse message packets */
1276     .rtcm_writer    = NULL,		/* don't send DGPS corrections */
1277     .init_query     = NULL,		/* non-perturbing initial query */
1278     .event_hook     = garmin_event_hook,/* lifetime ebent handler */
1279 #ifdef RECONFIGURE_ENABLE
1280     .speed_switcher = NULL,		/* no speed switcher */
1281     .mode_switcher  = NULL,	        /* Garmin USB Binary has no NMEA */
1282     .rate_switcher  = NULL,		/* no sample-rate switcher */
1283     .min_cycle.tv_sec  = 0,
1284     .min_cycle.tv_nsec = 10000000,	/* 10Hz */
1285 #endif /* RECONFIGURE_ENABLE */
1286 #ifdef CONTROLSEND_ENABLE
1287     .control_send   = garmin_control_send,	/* send raw bytes */
1288 #endif /* CONTROLSEND_ENABLE */
1289     .time_offset     = garmin_time_offset,
1290 };
1291 /* *INDENT-ON* */
1292 
1293 /* *INDENT-OFF* */
1294 const struct gps_type_t driver_garmin_ser_binary =
1295 {
1296     .type_name      = "Garmin Serial binary",	/* full name of type */
1297     .packet_type    = GARMIN_PACKET,	/* associated lexer packet type */
1298     .flags	    = DRIVER_STICKY,	/* remember this */
1299     .trigger        = NULL,		/* no trigger, it has a probe */
1300     .channels       = GARMIN_CHANNELS,	/* consumer-grade GPS */
1301     .probe_detect   = NULL,        	/* how to detect at startup time */
1302     .get_packet     = generic_get,       /* how to grab a packet */
1303     .parse_packet   = garmin_ser_parse,	/* parse message packets */
1304     .rtcm_writer    = NULL,		/* don't send DGPS corrections */
1305     .init_query     = NULL,		/* non-perturbing initial query */
1306     .event_hook     = NULL,	        /* lifetime event handler */
1307 #ifdef RECONFIGURE_ENABLE
1308     .speed_switcher = NULL,		/* no speed switcher */
1309     .mode_switcher  = garmin_switcher,	/* how to change modes */
1310     .rate_switcher  = NULL,		/* no sample-rate switcher */
1311     .min_cycle.tv_sec  = 0,
1312     .min_cycle.tv_nsec = 10000000,      /* 10Hz */
1313 #endif /* RECONFIGURE_ENABLE */
1314 #ifdef CONTROLSEND_ENABLE
1315     .control_send   = garmin_control_send,	/* send raw bytes */
1316 #endif /* CONTROLSEND_ENABLE */
1317     .time_offset     = garmin_time_offset,
1318 };
1319 /* *INDENT-ON* */
1320 
1321 #endif /* GARMIN_ENABLE */
1322 
1323 // vim: set expandtab shiftwidth=4
1324