2 * This file contains two drivers for Garmin receivers and some code
3 * shared by both drivers.
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.
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.
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
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.
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
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
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 intrinstic to USB bulk pipes.
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
45 * Application protocols are named A000 and then with different
46 * 3-digit numbres. They are carried over Link protocols.
48 * Thus, much of the higher-level code dealing the data formats is
49 * shared between USB Binary and Serial Binary.
51 * This code is partly from the Garmin IOSDK and partly from the
52 * sample code in the Linux garmin_gps driver.
54 * bad code by: Gary E. Miller <gem@rellim.com>
57 * -D 4 = packet details
58 * -D 5 = more packet details
59 * -D 6 = very excessive details
63 * do not have from garmin:
70 * hangs in the fread loop instead of keeping state and returning.
74 * ?? Add probe function for Serial Binary to start PVT output.
76 * This file is Copyright (c) 2010 by the GPSD project
77 * BSD terms apply: see the file COPYING in the distribution root for details.
80 #define __USE_POSIX199309 1
81 #include <sys/types.h>
82 #include <time.h> // for nanosleep()
91 #endif /* S_SPLINT_S */
95 #include "gpsd_config.h"
96 #if defined (HAVE_SYS_SELECT_H)
97 #include <sys/select.h>
100 #if defined(HAVE_STRINGS_H)
104 #if defined(HAVE_LIBUSB)
115 /* Used in Serial Physical Layer */
121 #define GARMIN_LAYERID_TRANSPORT (uint8_t) 0
122 #define GARMIN_LAYERID_APPL (uint32_t) 20
123 // Linux Garmin USB driver layer-id to use for some control mechanisms
124 #define GARMIN_LAYERID_PRIVATE 0x01106E4B
126 // packet ids used in private layer
127 #define PRIV_PKTID_SET_DEBUG 1
128 #define PRIV_PKTID_SET_MODE 2
129 #define PRIV_PKTID_INFO_REQ 3
130 #define PRIV_PKTID_INFO_RESP 4
131 #define PRIV_PKTID_RESET_REQ 5
132 #define PRIV_PKTID_SET_DEF_MODE 6
134 #define MODE_NATIVE 0
135 #define MODE_GARMIN_SERIAL 1
137 #define GARMIN_PKTID_TRANSPORT_START_SESSION_REQ 5
138 #define GARMIN_PKTID_TRANSPORT_START_SESSION_RESP 6
140 #define GARMIN_PKTID_PROTOCOL_ARRAY 253
141 #define GARMIN_PKTID_PRODUCT_RQST 254
142 #define GARMIN_PKTID_PRODUCT_DATA 255
144 #define GARMIN_PKTID_RMD41_DATA 41
146 #define GARMIN_PKTID_PVT_DATA 51
148 #define GARMIN_PKTID_RMD_DATA 52
150 #define GARMIN_PKTID_SAT_DATA 114
152 #define GARMIN_PKTID_L001_XFER_CMPLT 12
153 #define GARMIN_PKTID_L001_COMMAND_DATA 10
154 #define GARMIN_PKTID_L001_DATE_TIME_DATA 14
155 #define GARMIN_PKTID_L001_RECORDS 27
156 #define GARMIN_PKTID_L001_WPT_DATA 35
159 #define CMND_START_PVT_DATA 49
160 #define CMND_STOP_PVT_DATA 50
161 #define CMND_START_RM_DATA 110
163 #define MAX_BUFFER_SIZE 4096
165 #define GARMIN_CHANNELS 12
167 // something magic about 64, garmin driver will not return more than
168 // 64 at a time. If you read less than 64 bytes the next read will
169 // just get the last of the 64 byte buffer.
170 #define ASYNC_DATA_SIZE 64
174 // This is the data format of the satellite data from the garmin USB
178 int16_t snr; // 0 - 0xffff
181 uint8_t status; // bit 0, has ephemeris, 1, has diff correction
182 // bit 2 used in solution
186 /* Garmin D800_Pvt_Datetype_Type */
187 /* packet type: GARMIN_PKTID_PVT_DATA 52 */
188 /* This is the data format of the position data from the garmin USB */
191 float alt; /* altitude above WGS 84 (meters) */
192 float epe; /* estimated position error, 2 sigma (meters) */
193 float eph; /* epe, but horizontal only (meters) */
194 float epv; /* epe but vertical only (meters ) */
195 int16_t fix; /* 0 - failed integrity check
196 * 1 - invalid or unavailable fix
202 double gps_tow; /* gps time of week (seconds) */
203 double lat; /* ->latitude (radians) */
204 double lon; /* ->longitude (radians) */
205 float lon_vel; /* velocity east (meters/second) */
206 float lat_vel; /* velocity north (meters/second) */
207 float alt_vel; /* velocity up (meters/sec) */
208 // Garmin GPS25 uses pkt_id 0x28 and does not output the
210 float msl_hght; /* height of WGS 84 above MSL (meters) */
211 int16_t leap_sec; /* diff between GPS and UTC (seconds) */
212 int32_t grmn_days; /* days from UTC December 31st, 1989 to the
213 * beginning of the current week */
227 /* packet type: GARMIN_PKTID_RMD_DATA 53 */
228 /* seems identical to the packet id 0x29 from the Garmin GPS 25 */
233 cpo_rcv_sv_data sv[GARMIN_CHANNELS];
236 // This is the packet format to/from the Garmin USB
247 int8_t chars[MAX_BUFFER_SIZE];
248 uint8_t uchars[MAX_BUFFER_SIZE];
254 // useful funcs to read/write ints
255 // floats and doubles are Intel order only...
256 static inline void set_int16(uint8_t * buf, uint32_t value)
258 buf[0] = (uint8_t) (0x0FF & value);
259 buf[1] = (uint8_t) (0x0FF & (value >> 8));
262 static inline void set_int32(uint8_t * buf, uint32_t value)
264 buf[0] = (uint8_t) (0x0FF & value);
265 buf[1] = (uint8_t) (0x0FF & (value >> 8));
266 buf[2] = (uint8_t) (0x0FF & (value >> 16));
267 buf[3] = (uint8_t) (0x0FF & (value >> 24));
270 static inline uint16_t get_uint16(const uint8_t * buf)
272 return (uint16_t) (0xFF & buf[0])
273 | ((uint16_t) (0xFF & buf[1]) << 8);
276 static inline uint32_t get_int32(const uint8_t * buf)
278 return (uint32_t) (0xFF & buf[0])
279 | ((uint32_t) (0xFF & buf[1]) << 8)
280 | ((uint32_t) (0xFF & buf[2]) << 16)
281 | ((uint32_t) (0xFF & buf[3]) << 24);
284 // convert radians to degrees
285 static inline double radtodeg(double rad)
287 return (double)(rad * RAD_2_DEG);
290 static gps_mask_t PrintSERPacket(struct gps_device_t *session,
291 unsigned char pkt_id, int pkt_len,
293 static gps_mask_t PrintUSBPacket(struct gps_device_t *session,
296 gps_mask_t PrintSERPacket(struct gps_device_t *session, unsigned char pkt_id,
297 int pkt_len, unsigned char *buf)
302 uint16_t prod_id = 0;
308 char msg_buf[512] = "";
310 cpo_sat_data *sats = NULL;
311 cpo_pvt_data *pvt = NULL;
312 cpo_rcv_data *rmd = NULL;
314 gpsd_report(LOG_IO, "Garmin: PrintSERPacket(, %#02x, %#02x, )\n", pkt_id,
317 session->cycle_end_reliable = true;
321 gpsd_report(LOG_PROG, "Garmin: ACK\n");
324 gpsd_report(LOG_PROG, "Garmin: NAK\n");
326 case GARMIN_PKTID_L001_COMMAND_DATA:
327 prod_id = get_uint16((uint8_t *) buf);
331 msg = "Abort current xfer";
333 case CMND_START_PVT_DATA:
334 msg = "Start Xmit PVT data";
336 case CMND_STOP_PVT_DATA:
337 msg = "Stop Xmit PVT data";
339 case CMND_START_RM_DATA:
340 msg = "Start RMD data";
343 (void)snprintf(msg_buf, sizeof(msg_buf), "Unknown: %u",
344 (unsigned int)prod_id);
349 gpsd_report(LOG_PROG, "Garmin: Appl, Command Data: %s\n", msg);
351 case GARMIN_PKTID_PRODUCT_RQST:
352 gpsd_report(LOG_PROG, "Garmin: Appl, Product Data req\n");
354 case GARMIN_PKTID_PRODUCT_DATA:
355 prod_id = get_uint16((uint8_t *) buf);
356 ver = get_uint16((uint8_t *) & buf[2]);
357 maj_ver = (int)(ver / 100);
358 min_ver = (int)(ver - (maj_ver * 100));
359 gpsd_report(LOG_PROG, "Garmin: Appl, Product Data, sz: %d\n",
361 (void)snprintf(session->subtype, sizeof(session->subtype),
362 "%d: %d.%02d", (int)prod_id, maj_ver, min_ver);
363 gpsd_report(LOG_INF, "Garmin: Product ID: %d, SoftVer: %d.%02d\n",
364 prod_id, maj_ver, min_ver);
365 gpsd_report(LOG_INF, "Garmin: Product Desc: %s\n", &buf[4]);
367 gpsd_report(LOG_DATA, "Garmin: PRODUCT_DATA: subtype=%s mask=%s\n",
368 session->subtype, gpsd_maskdump(mask));
370 case GARMIN_PKTID_PVT_DATA:
371 gpsd_report(LOG_PROG, "Garmin: Appl, PVT Data Sz: %d\n", pkt_len);
373 pvt = (cpo_pvt_data *) buf;
375 // 631065600, unix seconds for 31 Dec 1989 Zulu
376 time_l = (time_t) (631065600 + (pvt->grmn_days * 86400));
377 // TODO, convert grmn_days to context->gps_week
378 time_l -= pvt->leap_sec;
379 session->context->leap_seconds = pvt->leap_sec;
380 session->context->valid = LEAP_SECOND_VALID;
381 // gps_tow is always like x.999 or x.998 so just round it
382 time_l += (time_t) round(pvt->gps_tow);
383 session->context->gps_tow = pvt->gps_tow;
384 session->newdata.time = (double)time_l;
385 gpsd_report(LOG_PROG, "Garmin: time_l: %ld\n", (long int)time_l);
387 session->newdata.latitude = radtodeg(pvt->lat);
388 /* sanity check the lat */
389 if (90.0 < session->newdata.latitude) {
390 session->newdata.latitude = 90.0;
391 gpsd_report(LOG_INF, "Garmin: ERROR: Latitude overrange\n");
392 } else if (-90.0 > session->newdata.latitude) {
393 session->newdata.latitude = -90.0;
395 "Garmin: ERROR: Latitude negative overrange\n");
397 session->newdata.longitude = radtodeg(pvt->lon);
398 /* sanity check the lon */
399 if (180.0 < session->newdata.longitude) {
400 session->newdata.longitude = 180.0;
401 gpsd_report(LOG_INF, "Garmin: ERROR: Longitude overrange\n");
402 } else if (-180.0 > session->newdata.longitude) {
403 session->newdata.longitude = -180.0;
405 "Garmin: ERROR: Longitude negative overrange\n");
407 // altitude over WGS84 converted to MSL
408 session->newdata.altitude = pvt->alt + pvt->msl_hght;
410 // geoid separation from WGS 84
411 // gpsd sign is opposite of garmin sign
412 session->gpsdata.separation = -pvt->msl_hght;
414 // Estimated position error in meters.
415 // We follow the advice at <http://gpsinformation.net/main/errors.htm>.
416 // If this assumption changes here, it should also change in
417 // nmea_parse.c where we analyze PGRME.
418 session->gpsdata.epe = pvt->epe * (GPSD_CONFIDENCE / CEP50_SIGMA);
419 /* eph is a circular error, sqrt(epx**2 + epy**2) */
420 session->newdata.epx = session->newdata.epy =
421 pvt->eph * (1 / sqrt(2)) * (GPSD_CONFIDENCE / CEP50_SIGMA);
422 session->newdata.epv = pvt->epv * (GPSD_CONFIDENCE / CEP50_SIGMA);
424 // convert lat/lon to directionless speed
425 session->newdata.speed = hypot(pvt->lon_vel, pvt->lat_vel);
427 // keep climb in meters/sec
428 session->newdata.climb = pvt->alt_vel;
430 track = atan2(pvt->lon_vel, pvt->lat_vel);
434 session->newdata.track = radtodeg(track);
441 session->gpsdata.status = STATUS_NO_FIX;
442 session->newdata.mode = MODE_NO_FIX;
446 session->gpsdata.status = STATUS_FIX;
447 session->newdata.mode = MODE_2D;
451 session->gpsdata.status = STATUS_FIX;
452 session->newdata.mode = MODE_3D;
455 // 2D Differential fix
456 session->gpsdata.status = STATUS_DGPS_FIX;
457 session->newdata.mode = MODE_2D;
460 // 3D differential fix
461 session->gpsdata.status = STATUS_DGPS_FIX;
462 session->newdata.mode = MODE_3D;
466 gpsd_report(LOG_PROG, "Garmin: Appl, mode %d, status %d\n",
467 session->newdata.mode, session->gpsdata.status);
469 gpsd_report(LOG_INF, "Garmin: UTC Time: %lf\n",
470 session->newdata.time);
472 "Garmin: Geoid Separation (MSL-WGS84): from garmin %lf, calculated %lf\n",
474 wgs84_separation(session->newdata.latitude,
475 session->newdata.longitude));
478 "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",
479 pvt->alt, pvt->epe, pvt->eph, pvt->epv, pvt->fix,
480 pvt->gps_tow, session->newdata.latitude,
481 session->newdata.longitude, pvt->lon_vel, pvt->lat_vel,
482 pvt->alt_vel, pvt->msl_hght, pvt->leap_sec,
485 if (session->newdata.mode > MODE_NO_FIX) {
486 /* data only valid with a fix */
488 TIME_IS | LATLON_IS | ALTITUDE_IS | STATUS_IS | MODE_IS |
489 SPEED_IS | TRACK_IS | CLIMB_IS | HERR_IS | VERR_IS | PERR_IS |
490 CLEAR_IS | REPORT_IS;
492 gpsd_report(LOG_DATA,
493 "Garmin: PVT_DATA: time=%.2f, lat=%.2f lon=%.2f "
494 "speed=%.2f track=%.2f climb=%.2f "
495 "epx=%.2f epy=%.2f epv=%.2f "
496 "mode=%d status=%d mask=%s\n",
497 session->newdata.time,
498 session->newdata.latitude,
499 session->newdata.longitude,
500 session->newdata.speed,
501 session->newdata.track,
502 session->newdata.climb,
503 session->newdata.epx,
504 session->newdata.epy,
505 session->newdata.epv,
506 session->newdata.mode,
507 session->gpsdata.status, gpsd_maskdump(mask));
509 case GARMIN_PKTID_RMD_DATA:
510 case GARMIN_PKTID_RMD41_DATA:
511 rmd = (cpo_rcv_data *) buf;
512 gpsd_report(LOG_IO, "Garmin: PVT RMD Data Sz: %d\n", pkt_len);
513 gpsd_report(LOG_PROG, "Garmin: PVT RMD rcvr_tow: %f, rcvr_wn: %d\n",
514 rmd->rcvr_tow, rmd->rcvr_wn);
515 for (i = 0; i < GARMIN_CHANNELS; i++) {
517 "Garmin: PVT RMD Sat: %3u, cycles: %9u, pr: %16.6f, "
518 "phase: %7.3f, slp_dtct: %3s, snr: %3u, Valid: %3s\n",
519 rmd->sv[i].svid + 1, rmd->sv[i].cycles, rmd->sv[i].pr,
520 (rmd->sv[i].phase * 360.0) / 2048.0,
521 rmd->sv[i].slp_dtct != '\0' ? "Yes" : "No",
523 rmd->sv[i].valid != '\0' ? "Yes" : "No");
527 case GARMIN_PKTID_SAT_DATA:
528 gpsd_report(LOG_PROG, "Garmin: SAT Data Sz: %d\n", pkt_len);
529 sats = (cpo_sat_data *) buf;
531 session->gpsdata.satellites_used = 0;
532 memset(session->gpsdata.used, 0, sizeof(session->gpsdata.used));
533 gpsd_zero_satellites(&session->gpsdata);
534 for (i = 0, j = 0; i < GARMIN_CHANNELS; i++, sats++) {
536 "Garmin: Sat %3d, snr: %5d, elev: %2d, Azmth: %3d, Stat: %x\n",
537 sats->svid, sats->snr, sats->elev, sats->azmth,
540 if (255 == (int)sats->svid) {
541 // Garmin uses 255 for empty
542 // gpsd uses 0 for empty
546 session->gpsdata.PRN[j] = (int)sats->svid;
547 session->gpsdata.azimuth[j] = (int)sats->azmth;
548 session->gpsdata.elevation[j] = (int)sats->elev;
549 // Garmin does not document this. snr is in dB*100
550 // Known, but not seen satellites have a dB value of -1*100
551 session->gpsdata.ss[j] = (float)(sats->snr / 100.0);
552 if (session->gpsdata.ss[j] < 0.0) {
553 session->gpsdata.ss[j] = 0.0;
555 // FIX-ME: Garmin documents this, but Daniel Dorau
556 // <daniel.dorau@gmx.de> says the behavior on his GPSMap60CSX
558 if ((uint8_t) 0 != (sats->status & 4)) {
560 session->gpsdata.used[session->gpsdata.satellites_used++]
563 session->gpsdata.satellites_visible++;
567 session->gpsdata.skyview_time = NAN;
568 mask |= SATELLITE_IS | USED_IS;
569 gpsd_report(LOG_DATA,
570 "Garmin: SAT_DATA: visible=%d used=%d mask=%s\n",
571 session->gpsdata.satellites_visible,
572 session->gpsdata.satellites_used, gpsd_maskdump(mask));
574 case GARMIN_PKTID_PROTOCOL_ARRAY:
575 // this packet is never requested, it just comes, in some case
576 // after a GARMIN_PKTID_PRODUCT_RQST
577 gpsd_report(LOG_INF, "Garmin: Appl, Product Capability, sz: %d\n",
579 for (i = 0; i < pkt_len; i += 3) {
580 gpsd_report(LOG_INF, "Garmin: %c%03d\n", buf[i],
581 get_uint16((uint8_t *) & buf[i + 1]));
585 gpsd_report(LOG_WARN,
586 "Garmin: Unknown packet id: %#02x, Sz: %#02x, pkt:%s\n",
587 pkt_id, pkt_len, gpsd_hexdump_wrapper(buf,
592 gpsd_report(LOG_IO, "Garmin: PrintSERPacket(, %#02x, %#02x, ) = %s\n",
593 pkt_id, pkt_len, gpsd_maskdump(mask));
599 // For debugging, decodes and prints some known packets.
600 static gps_mask_t PrintUSBPacket(struct gps_device_t *session, Packet_t * pkt)
606 uint16_t prod_id = 0;
609 uint32_t mDataSize = get_int32((uint8_t *) & pkt->mDataSize);
612 uint8_t *buffer = (uint8_t *) pkt;
614 gpsd_report(LOG_PROG, "Garmin: PrintUSBPacket()\n");
616 if (DLE == pkt->mPacketType) {
617 gpsd_report(LOG_PROG, "Garmin: really a SER packet!\n");
618 return PrintSERPacket(session,
619 (unsigned char)buffer[1],
620 (int)buffer[2], (unsigned char *)(buffer + 3));
623 if (4096 < mDataSize) {
624 gpsd_report(LOG_WARN, "Garmin: bogus packet, size too large=%d\n",
629 (void)snprintf(session->gpsdata.tag, sizeof(session->gpsdata.tag), "%u",
630 (unsigned int)pkt->mPacketType);
631 switch (pkt->mPacketType) {
632 case GARMIN_LAYERID_TRANSPORT:
633 /* Garmin USB layer specific */
634 switch (pkt->mPacketId) {
635 case GARMIN_PKTID_TRANSPORT_START_SESSION_REQ:
636 gpsd_report(LOG_PROG, "Garmin: Transport, Start Session req\n");
638 case GARMIN_PKTID_TRANSPORT_START_SESSION_RESP:
639 mode = get_int32(&pkt->mData.uchars[0]);
640 gpsd_report(LOG_PROG,
641 "Garmin: Transport, Start Session resp, unit: 0x%x\n",
645 gpsd_report(LOG_PROG,
646 "Garmin: Transport, Packet: Type %d %d %d, ID: %d, Sz: %d\n",
647 pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
648 pkt->mPacketId, mDataSize);
652 case GARMIN_LAYERID_APPL:
653 /* raw data transport, shared with Garmin Serial Driver */
655 mask = PrintSERPacket(session,
656 (unsigned char)pkt->mPacketId,
658 (unsigned char *)pkt->mData.uchars);
661 // private, garmin USB kernel driver specific
662 switch (pkt->mPacketId) {
663 case PRIV_PKTID_SET_MODE:
664 prod_id = get_uint16(&pkt->mData.uchars[0]);
665 gpsd_report(LOG_PROG, "Garmin: Private, Set Mode: %d\n", prod_id);
667 case PRIV_PKTID_INFO_REQ:
668 gpsd_report(LOG_PROG, "Garmin: Private, ID: Info Req\n");
670 case PRIV_PKTID_INFO_RESP:
671 veri = get_int32(pkt->mData.uchars);
672 maj_ver = (int)(veri >> 16);
673 min_ver = (int)(veri & 0xffff);
674 mode = get_int32(&pkt->mData.uchars[4]);
675 serial = get_int32(&pkt->mData.uchars[8]);
676 gpsd_report(LOG_PROG, "Garmin: Private, ID: Info Resp\n");
678 "Garmin: USB Driver found, Version %d.%d, Mode: %d, GPS Serial# %u\n",
679 maj_ver, min_ver, mode, serial);
682 gpsd_report(LOG_PROG, "Garmin: Private, Packet: ID: %d, Sz: %d\n",
683 pkt->mPacketId, mDataSize);
688 gpsd_report(LOG_PROG,
689 "Garmin: Packet: Type %d %d %d, ID: %d, Sz: %d\n",
690 pkt->mPacketType, pkt->mReserved1, pkt->mReserved2,
691 pkt->mPacketId, mDataSize);
701 /* build and send a packet w/ USB protocol */
702 static void Build_Send_USB_Packet(struct gps_device_t *session,
703 uint32_t layer_id, uint32_t pkt_id,
704 uint32_t length, uint32_t data)
706 uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
707 Packet_t *thePacket = (Packet_t *) buffer;
708 ssize_t theBytesReturned = 0;
709 ssize_t theBytesToWrite = 12 + (ssize_t) length;
711 set_int32(buffer, layer_id);
712 set_int32(buffer + 4, pkt_id);
713 set_int32(buffer + 8, length);
715 set_int16(buffer + 12, data);
716 } else if (4 == length) {
717 set_int32(buffer + 12, data);
720 gpsd_report(LOG_IO, "Garmin: SendPacket(), writing %d bytes: %s\n",
722 gpsd_hexdump_wrapper(thePacket, theBytesToWrite, LOG_IO));
724 (void)PrintUSBPacket(session, thePacket);
726 theBytesReturned = gpsd_write(session, thePacket,
727 (size_t) theBytesToWrite);
728 gpsd_report(LOG_IO, "Garmin: SendPacket(), wrote %zd bytes\n",
732 // If the packet size was an exact multiple of the USB packet
733 // size, we must make a final write call with no data
735 // as a practical matter no known packets are 64 bytes long so
738 // So here goes just in case
739 if (0 == (theBytesToWrite % ASYNC_DATA_SIZE)) {
741 theBytesReturned = gpsd_write(session, &n, 0);
745 /* build and send a packet in serial protocol */
746 /* layer_id unused */
747 // FIX-ME: This should go through the common message buffer someday
748 static void Build_Send_SER_Packet(struct gps_device_t *session,
749 uint32_t layer_id UNUSED, uint32_t pkt_id,
750 uint32_t length, uint32_t data)
752 uint8_t *buffer = (uint8_t *) session->driver.garmin.Buffer;
753 uint8_t *buffer0 = buffer;
754 Packet_t *thePacket = (Packet_t *) buffer;
755 ssize_t theBytesReturned = 0;
756 ssize_t theBytesToWrite = 6 + (ssize_t) length;
759 *buffer++ = (uint8_t) DLE;
760 *buffer++ = (uint8_t) pkt_id;
762 *buffer++ = (uint8_t) length;
764 /* ??? What is this doing? */
766 /* carefull! no DLE stuffing here! */
767 set_int16(buffer, data);
770 } else if (4 == length) {
771 /* carefull! no DLE stuffing here! */
772 set_int32(buffer, data);
778 /* ??? How is data copied to the buffer? */
783 if (DLE == -chksum) {
784 /* stuff another DLE */
785 *buffer++ = (uint8_t) DLE;
789 *buffer++ = (uint8_t) DLE;
790 *buffer++ = (uint8_t) ETX;
793 gpsd_report(LOG_IO, "Garmin: SendPacket(), writing %zd bytes: %s\n",
795 gpsd_hexdump_wrapper(thePacket, (size_t) theBytesToWrite,
798 (void)PrintSERPacket(session,
799 (unsigned char)buffer0[1],
800 (int)buffer0[2], (unsigned char *)(buffer0 + 3));
802 theBytesReturned = gpsd_write(session, thePacket,
803 (size_t) theBytesToWrite);
804 gpsd_report(LOG_IO, "Garmin: SendPacket(), wrote %zd bytes\n",
809 #if defined(HAVE_LIBUSB) || defined(S_SPLINT_S)
811 * is_usb_device() - is a specified device USB matching given vendor/product?
813 * BUG: Doesn't actually match against path yet. Must finish this function
814 * by querying /sys/dev/char, either directly or using libudev. Greg KH
815 * assures this is possible, though he is vague about how.
817 * libudev: http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/
819 /*@-compdef -usedef@*/
820 static bool is_usb_device(const char *path UNUSED, int vendor, int product)
823 libusb_device **list;
828 gpsd_report(LOG_SHOUT, "attempting USB device enumeration.\n");
829 /*@i2@*/ libusb_init(NULL);
832 if ((cnt = libusb_get_device_list(NULL, &list)) < 0) {
833 gpsd_report(LOG_ERROR, "USB device list call failed.\n");
834 /*@i1@*/ libusb_exit(NULL);
839 for (i = 0; i < cnt; i++) {
840 struct libusb_device_descriptor desc;
841 libusb_device *dev = list[i];
843 int r = libusb_get_device_descriptor(dev, &desc);
845 gpsd_report(LOG_ERROR,
846 "USB descriptor fetch failed on device %zd.\n", i);
850 /* we can extract device descriptor data */
851 gpsd_report(LOG_SHOUT, "%04x:%04x (bus %d, device %d)\n",
852 desc.idVendor, desc.idProduct,
853 libusb_get_bus_number(dev),
854 libusb_get_device_address(dev));
856 /* we match if vendor and product ID are right */
857 if (desc.idVendor == 0x91e && desc.idProduct == 3) {
863 gpsd_report(LOG_SHOUT, "vendor/product match with %04x:%04x %sfound\n",
864 vendor, product, found ? "" : "not ");
865 libusb_free_device_list(list, 1);
866 /*@i1@*/ libusb_exit(NULL);
870 /*@-compdef -usedef@*/
871 #endif /* HAVE_LIBUSB || S_SPLINT_S */
874 * garmin_usb_detect() - detect a Garmin USB device connected to ession fd.
876 * This is ONLY for USB devices reporting as: 091e:0003.
878 * This driver ONLY works in Linux and ONLY when the the garmin_gps kernel
879 * module is installed.
881 * This is only necessary because under Linux Garmin USB devices need a
882 * kernel module rather than being normal USB-serial devices.
884 * The actual wire protocol from the Garmin device is very strange. There
885 * are no delimiters. End of packet is signaled by a zero-length read
886 * on the USB device, and start of packet is the next read. You can't just
887 * ignore the zero reads and pass the data through - you'd never be able
888 * to tell where the packet boundaries are.
890 * The garmin_usb module's job is to grab the packet and frame it in
891 * DLEs (with DLE stuffing). This makes the USB packets look as
892 * though they came from a regular Garmin *serial* device, which is how
893 * most of the processing for both types can be unified here.
895 * return 1 is device found
898 static bool garmin_usb_detect(struct gps_device_t *session)
900 #if defined(__linux__) || defined(S_SPLINT_S)
902 * Only perform this check if we're looking at a USB-serial
903 * device. This prevents drivers for attached serial GPSes
904 * fronm being rudely elbowed aside by this one if they happen
905 * to be trying to coexist with the Garmin.
907 if (session->sourcetype != source_usb)
911 if (!is_usb_device(session->gpsdata.dev.path, 0x091e, 0x0003))
915 * This is ONLY for USB devices reporting as: 091e:0003.
917 * Check that the garmin_gps driver is installed in the kernel
918 * and that an active USB device is using it.
920 * BUG: It does not yet check that the currect device is the one
921 * attached to the Garmin. So if you have a Garmin and another
922 * USB gps this could be a problem.
924 * Return true if garmin_gps device found, false otherwise.
930 /* check for garmin USB serial driver -- very Linux-specific */
931 if (access("/sys/module/garmin_gps", R_OK) != 0) {
932 gpsd_report(LOG_WARN,
933 "Garmin: garmin_gps Linux USB module not active.\n");
936 /* check for a garmin_gps device in /proc
938 if (NULL != (fp = fopen("/proc/bus/usb/devices", "r"))) {
941 while (0 != fgets(buf, (int)sizeof(buf), fp)) {
942 if (strstr(buf, "garmin_gps")) {
949 // no device using garmin_gps now
950 gpsd_report(LOG_WARN,
951 "Garmin: garmin_gps not in /proc/bus/usb/devices.\n");
952 gpsd_report(LOG_WARN,
953 "Garmin: garmin_gps driver present, but not in use\n");
957 gpsd_report(LOG_WARN,
958 "Garmin: Can't open /proc/bus/usb/devices, will try anyway\n");
960 #endif /* HAVE_LIBUSB */
962 if (!gpsd_set_raw(session)) {
963 gpsd_report(LOG_ERROR,
964 "Garmin: garmin_usb_detect: error changing port attributes: %s\n",
969 Packet_t *thePacket = NULL;
970 uint8_t *buffer = NULL;
971 /* reset the buffer and buffer length */
972 memset(session->driver.garmin.Buffer, 0,
973 sizeof(session->driver.garmin.Buffer));
974 session->driver.garmin.BufferLen = 0;
976 if (sizeof(session->driver.garmin.Buffer) < sizeof(Packet_t)) {
977 gpsd_report(LOG_ERROR,
978 "Garmin: garmin_usb_detect: Compile error, garmin.Buffer too small.\n",
983 buffer = (uint8_t *) session->driver.garmin.Buffer;
984 thePacket = (Packet_t *) buffer;
985 #endif /* __UNUSED__ */
987 // set Mode 1, mode 0 is broken somewhere past 2.6.14
989 gpsd_report(LOG_PROG, "Garmin: Set garmin_gps driver mode = 0\n");
990 Build_Send_USB_Packet(session, GARMIN_LAYERID_PRIVATE,
991 PRIV_PKTID_SET_MODE, 4, MODE_GARMIN_SERIAL);
992 // expect no return packet !?
998 #endif /* __linux__ || S_SPLINT_S */
1001 static void garmin_event_hook(struct gps_device_t *session, event_t event)
1004 * FIX-ME: It might not be necessary to call this on reactivate.
1005 * Experiment to see if the holds its settings through a close.
1007 if (event == event_identified || event == event_reactivate) {
1008 // Tell the device to send product data
1009 gpsd_report(LOG_PROG, "Garmin: Get Product Data\n");
1010 Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1011 GARMIN_PKTID_PRODUCT_RQST, 0, 0);
1013 // turn on PVT data 49
1014 gpsd_report(LOG_PROG, "Garmin: Set to send reports every 1 second\n");
1016 Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1017 GARMIN_PKTID_L001_COMMAND_DATA, 2,
1018 CMND_START_PVT_DATA);
1021 // turn on RMD data 110
1022 gpsd_report(LOG_PROG, "Garmin: Set to send Raw sat data\n");
1023 Build_Send_SER_Packet(session, GARMIN_LAYERID_APPL,
1024 GARMIN_PKTID_L001_COMMAND_DATA, 2,
1025 CMND_START_RM_DATA);
1028 if (event == event_deactivate)
1029 /* FIX-ME: is any action needed, or is closing the port sufficient? */
1030 gpsd_report(LOG_PROG, "Garmin: garmin_close()\n");
1033 #define Send_ACK() Build_Send_SER_Packet(session, 0, ACK, 0, 0)
1034 #define Send_NAK() Build_Send_SER_Packet(session, 0, NAK, 0, 0)
1037 gps_mask_t garmin_ser_parse(struct gps_device_t *session)
1039 unsigned char *buf = session->packet.outbuffer;
1040 size_t len = session->packet.outbuflen;
1041 unsigned char data_buf[MAX_BUFFER_SIZE];
1047 unsigned char pkt_id = 0;
1048 unsigned char pkt_len = 0;
1049 unsigned char chksum = 0;
1050 gps_mask_t mask = 0;
1052 gpsd_report(LOG_RAW, "Garmin: garmin_ser_parse()\n");
1055 /* minimum packet; <DLE> [pkt id] [length=0] [chksum] <DLE> <STX> */
1057 gpsd_report(LOG_RAW + 1, "Garmin: serial too short: %zd\n", len);
1061 for (i = 0; i < (int)len; i++) {
1062 gpsd_report(LOG_RAW + 1, "Garmin: Char: %#02x\n", buf[i]);
1065 if ('\x10' != buf[0]) {
1067 gpsd_report(LOG_RAW + 1, "Garmin: buf[0] not DLE\n");
1073 if ('\x10' == pkt_id) {
1074 if ('\x10' != buf[n++]) {
1076 gpsd_report(LOG_RAW + 1, "Garmin: Bad pkt_id %#02x\n", pkt_id);
1083 if ('\x10' == pkt_len) {
1084 if ('\x10' != buf[n++]) {
1085 gpsd_report(LOG_RAW + 1, "Garmin: Bad pkt_len %#02x\n", pkt_len);
1091 for (i = 0; i < 256; i++) {
1093 if ((int)pkt_len == data_index) {
1098 gpsd_report(LOG_RAW + 1, "Garmin: Packet too short %zd < %zd\n",
1108 gpsd_report(LOG_RAW + 1, "Garmin: Bad DLE %#02x\n", c);
1113 data_buf[data_index++] = c;
1122 gpsd_report(LOG_RAW + 1,
1123 "Garmin: No checksum, Packet too short %zd < %zd\n", len,
1132 gpsd_report(LOG_RAW + 1,
1133 "Garmin: No final DLE, Packet too short %zd < %zd\n", len,
1140 gpsd_report(LOG_RAW + 1, "Garmin: Final DLE not DLE\n");
1146 gpsd_report(LOG_RAW + 1,
1147 "Garmin: No final ETX, Packet too short %zd < %zd\n", len,
1154 gpsd_report(LOG_RAW + 1, "Garmin: Final ETX not ETX\n");
1159 /*@ -usedef -compdef @*/
1160 for (i = 0; i < data_index; i++) {
1161 gpsd_report(LOG_RAW + 1, "Garmin: Char: %#02x\n", data_buf[i]);
1166 "Garmin: garmin_ser_parse() Type: %#02x, Len: %#02x, chksum: %#02x\n",
1167 pkt_id, pkt_len, chksum);
1168 mask = PrintSERPacket(session, pkt_id, pkt_len, data_buf);
1170 // sending ACK too soon might hang the session
1171 // so send ACK last, after a pause
1174 /*@ +usedef +compdef @*/
1175 gpsd_report(LOG_IO, "Garmin: garmin_ser_parse( ) = %s\n",
1176 gpsd_maskdump(mask));
1182 #ifdef ALLOW_RECONFIGURE
1183 static void settle(void)
1185 struct timespec delay, rem;
1186 /*@ -type -unrecog @*/
1187 memset(&delay, 0, sizeof(delay));
1189 delay.tv_nsec = 333000000L;
1190 nanosleep(&delay, &rem);
1191 /*@ +type +unrecog @*/
1194 static void garmin_switcher(struct gps_device_t *session, int mode)
1196 if (mode == MODE_NMEA) {
1198 const char switcher[] =
1199 { 0x10, 0x0A, 0x02, 0x26, 0x00, 0xCE, 0x10, 0x03 };
1200 // Note hard-coded string length in the next line...
1201 int status = (int)gpsd_write(session, switcher, sizeof(switcher));
1203 if (status == (int)sizeof(switcher)) {
1205 "Garmin: => GPS: turn off binary %02x %02x %02x... \n",
1206 switcher[0], switcher[1], switcher[2]);
1208 gpsd_report(LOG_ERROR, "Garmin: => GPS: FAILED\n");
1210 settle(); // wait 333mS, essential!
1212 /* once a sec, no binary, no averaging, NMEA 2.3, WAAS */
1213 (void)nmea_send(session, "$PGRMC1,1,1");
1214 //(void)nmea_send(fd, "$PGRMC1,1,1,1,,,,2,W,N");
1215 (void)nmea_send(session, "$PGRMI,,,,,,,R");
1216 settle(); // wait 333mS, essential!
1218 (void)nmea_send(session, "$PGRMC1,1,2,1,,,,2,W,N");
1219 (void)nmea_send(session, "$PGRMI,,,,,,,R");
1220 settle(); // wait 333mS, essential!
1223 #endif /* ALLOW_RECONFIGURE */
1225 #ifdef ALLOW_CONTROLSEND
1226 static ssize_t garmin_control_send(struct gps_device_t *session,
1227 char *buf, size_t buflen)
1228 /* not used by the daemon, it's for gpsctl and friends */
1230 /*@ -mayaliasunique @*/
1231 session->msgbuflen = buflen;
1232 (void)memcpy(session->msgbuf, buf, buflen);
1233 return gpsd_write(session, session->msgbuf, session->msgbuflen);
1234 /*@ +mayaliasunique @*/
1236 #endif /* ALLOW_CONTROLSEND */
1238 #ifdef NTPSHM_ENABLE
1239 static double garmin_ntp_offset(struct gps_device_t *session)
1241 if (session->sourcetype == source_usb) {
1242 return 0.035; /* Garmin USB, expect +/- 40mS jitter */
1244 /* only two sentences ships time */
1245 /* but the PVT data is always first */
1246 switch (session->gpsdata.dev.baudrate) {
1248 return 0.430; /* TBD */
1250 return 0.430; /* tested 12Arp10 */
1252 return 0.430; /* TBD */
1254 return 0.430; /* TBD */
1256 return 0.430; /* WTF? WAG */
1258 #endif /* NTPSHM_ENABLE */
1260 /* this is everything we export */
1262 static int GetPacket(struct gps_device_t *session);
1263 //-----------------------------------------------------------------------------
1264 // Gets a single packet.
1265 // this is odd, the garmin usb driver will only return 64 bytes, or less
1266 // at a time, no matter what you ask for.
1268 // is you ask for less than 64 bytes then the next packet will include
1269 // just the remaining bytes of the last 64 byte packet.
1271 // Reading a packet of length Zero, or less than 64, signals the end of
1272 // the entire packet.
1274 // The Garmin sample WinXX code also assumes the same behavior, so
1275 // maybe it is something in the USB protocol.
1277 // Return: 0 = got a good packet
1279 // 1 = got partial packet
1280 static int GetPacket(struct gps_device_t *session)
1282 struct timespec delay, rem;
1284 // int x = 0; // for debug dump
1286 memset(session->driver.garmin.Buffer, 0, sizeof(Packet_t));
1287 memset(&delay, 0, sizeof(delay));
1288 session->driver.garmin.BufferLen = 0;
1289 session->packet.outbuflen = 0;
1291 gpsd_report(LOG_IO, "Garmin: GetPacket()\n");
1293 for (cnt = 0; cnt < 10; cnt++) {
1295 // Read async data until the driver returns less than the
1296 // max async data size, which signifies the end of a packet
1298 // not optimal, but given the speed and packet nature of
1299 // the USB not too bad for a start
1300 ssize_t theBytesReturned = 0;
1301 uint8_t *buf = (uint8_t *) session->driver.garmin.Buffer;
1302 Packet_t *thePacket = (Packet_t *) buf;
1305 read(session->gpsdata.gps_fd,
1306 buf + session->driver.garmin.BufferLen, ASYNC_DATA_SIZE);
1307 // zero byte returned is a legal value and denotes the end of a
1309 if (0 > theBytesReturned) {
1311 // or EAGAIN, but O_NONBLOCK is never set
1312 gpsd_report(LOG_ERROR,
1313 "Garmin: GetPacket() read error=%d, errno=%d\n",
1314 theBytesReturned, errno);
1317 gpsd_report(LOG_RAW, "Garmin: got %d bytes\n", theBytesReturned);
1319 gpsd_report(LOG_IO, "Garmin: getPacket(), got %d bytes: %s\n",
1321 gpsd_hexdump_wrapper(thePacket, theBytesReturned,
1325 session->driver.garmin.BufferLen += theBytesReturned;
1326 if (256 <= session->driver.garmin.BufferLen) {
1327 // really bad read error...
1328 gpsd_report(LOG_ERROR,
1329 "Garmin: GetPacket() packet too long, %ld > 255 !\n",
1330 session->driver.garmin.BufferLen);
1331 session->driver.garmin.BufferLen = 0;
1334 pkt_size = 12 + get_int32((uint8_t *) & thePacket->mDataSize);
1335 if (12 <= session->driver.garmin.BufferLen) {
1336 // have enough data to check packet size
1337 if (session->driver.garmin.BufferLen > pkt_size) {
1338 // wrong amount of data in buffer
1339 gpsd_report(LOG_ERROR,
1340 "Garmin: GetPacket() packet size wrong! Packet: %ld, s/b %ld\n",
1341 session->driver.garmin.BufferLen, pkt_size);
1342 session->driver.garmin.BufferLen = 0;
1346 if (64 > theBytesReturned) {
1347 // zero length, or short, read is a flag for got the whole packet
1354 delay.tv_nsec = 3330000L;
1355 while (nanosleep(&delay, &rem) == -1)
1359 // dump the individual bytes, debug only
1360 // for ( x = 0; x < session->driver.garmin.BufferLen; x++ ) {
1361 // gpsd_report(LOG_RAW+1, "Garmin: p[%d] = %x\n", x, session->driver.garmin.Buffer[x]);
1364 gpsd_report(LOG_ERROR,
1365 "Garmin: GetPacket() packet too long or too slow!\n");
1369 gpsd_report(LOG_RAW, "Garmin: GotPacket() sz=%d \n",
1370 session->driver.garmin.BufferLen);
1371 session->packet.outbuflen = session->driver.garmin.BufferLen;
1375 static gps_mask_t garmin_usb_parse(struct gps_device_t *session)
1377 gpsd_report(LOG_PROG, "Garmin: garmin_usb_parse()\n");
1378 return PrintUSBPacket(session,
1379 (Packet_t *) session->driver.garmin.Buffer);
1382 static ssize_t garmin_get_packet(struct gps_device_t *session)
1384 return (ssize_t) (0 == GetPacket(session) ? 1 : 0);
1388 const struct gps_type_t garmin_usb_binary_old =
1390 .type_name = "Garmin USB binary", /* full name of type */
1391 .packet_type = GARMIN_PACKET; /* associated lexer packet type */
1392 .trigger = NULL, /* no trigger, it has a probe */
1393 .channels = GARMIN_CHANNELS, /* consumer-grade GPS */
1394 .probe_detect = garmin_usb_detect,/* how to detect at startup time */
1395 .get_packet = garmin_get_packet,/* how to grab a packet */
1396 .parse_packet = garmin_usb_parse, /* parse message packets */
1397 .rtcm_writer = NULL, /* don't send DGPS corrections */
1398 .event_hook = garmin_event_hook,/* lifetime event handler */
1399 #ifdef ALLOW_RECONFIGURE
1400 .speed_switcher = NULL, /* no speed switcher */
1401 .mode_switcher = NULL, /* no mode switcher */
1402 .rate_switcher = NULL, /* no sample-rate switcher */
1403 .min_cycle = 1, /* not relevant, no rate switch */
1404 #endif /* ALLOW_RECONFIGURE */
1405 #ifdef ALLOW_CONTROLSEND
1406 .control_send = garmin_control_send, /* send raw bytes */
1407 #endif /* ALLOW_CONTROLSEND */
1408 #ifdef NTPSHM_ENABLE
1409 .ntp_offset = garmin_ntp_offset,
1410 #endif /* NTPSHM_ ENABLE */
1413 #endif /* __UNUSED__ */
1416 const struct gps_type_t garmin_usb_binary =
1418 .type_name = "Garmin USB binary", /* full name of type */
1419 .packet_type = GARMIN_PACKET, /* associated lexer packet type */
1420 .trigger = NULL, /* no trigger, it has a probe */
1421 .channels = GARMIN_CHANNELS, /* consumer-grade GPS */
1422 .probe_detect = garmin_usb_detect,/* how to detect at startup time */
1423 .get_packet = generic_get, /* how to grab a packet */
1424 .parse_packet = garmin_ser_parse, /* parse message packets */
1425 .rtcm_writer = NULL, /* don't send DGPS corrections */
1426 .event_hook = garmin_event_hook,/* lifetime ebent handler */
1427 #ifdef ALLOW_RECONFIGURE
1428 .speed_switcher = NULL, /* no speed switcher */
1429 .mode_switcher = NULL, /* Garmin USB Binary has no NMEA */
1430 .rate_switcher = NULL, /* no sample-rate switcher */
1431 .min_cycle = 1, /* not relevant, no rate switch */
1432 #endif /* ALLOW_RECONFIGURE */
1433 #ifdef ALLOW_CONTROLSEND
1434 .control_send = garmin_control_send, /* send raw bytes */
1435 #endif /* ALLOW_CONTROLSEND */
1436 #ifdef NTPSHM_ENABLE
1437 .ntp_offset = garmin_ntp_offset,
1438 #endif /* NTPSHM_ ENABLE */
1443 const struct gps_type_t garmin_ser_binary =
1445 .type_name = "Garmin Serial binary", /* full name of type */
1446 .packet_type = GARMIN_PACKET, /* associated lexer packet type */
1447 .trigger = NULL, /* no trigger, it has a probe */
1448 .channels = GARMIN_CHANNELS, /* consumer-grade GPS */
1449 .probe_detect = NULL, /* how to detect at startup time */
1450 .get_packet = generic_get, /* how to grab a packet */
1451 .parse_packet = garmin_ser_parse, /* parse message packets */
1452 .rtcm_writer = NULL, /* don't send DGPS corrections */
1453 .event_hook = NULL, /* lifetime event handler */
1454 #ifdef ALLOW_RECONFIGURE
1455 .speed_switcher = NULL, /* no speed switcher */
1456 .mode_switcher = garmin_switcher, /* how to change modes */
1457 .rate_switcher = NULL, /* no sample-rate switcher */
1458 .min_cycle = 1, /* not relevant, no rate switch */
1459 #endif /* ALLOW_RECONFIGURE */
1460 #ifdef ALLOW_CONTROLSEND
1461 .control_send = garmin_control_send, /* send raw bytes */
1462 #endif /* ALLOW_CONTROLSEND */
1463 #ifdef NTPSHM_ENABLE
1464 .ntp_offset = garmin_ntp_offset,
1465 #endif /* NTPSHM_ ENABLE */
1469 #endif /* GARMIN_ENABLE */