1 /*
2  * This file is Copyright (c) 2010-2018 by the GPSD project
3  * SPDX-License-Identifier: BSD-2-clause
4  */
5 
6 #include "gpsd_config.h"  /* must be before all includes */
7 
8 #include <assert.h>
9 #include <ctype.h>
10 #include <stdarg.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include "gpsd.h"
18 #include "bits.h"		/* for getbeu16(), to extract big-endian words */
19 #include "strfuncs.h"
20 
generic_get(struct gps_device_t * session)21 ssize_t generic_get(struct gps_device_t *session)
22 {
23     return packet_get(session->gpsdata.gps_fd, &session->lexer);
24 }
25 
generic_parse_input(struct gps_device_t * session)26 gps_mask_t generic_parse_input(struct gps_device_t *session)
27 {
28     if (session->lexer.type == BAD_PACKET)
29 	return 0;
30     else if (session->lexer.type == COMMENT_PACKET) {
31 	gpsd_set_century(session);
32 	return 0;
33 #ifdef NMEA0183_ENABLE
34     } else if (session->lexer.type == NMEA_PACKET) {
35 	const struct gps_type_t **dp;
36 	gps_mask_t st = 0;
37 	char *sentence = (char *)session->lexer.outbuffer;
38 
39 	if (sentence[strlen(sentence)-1] != '\n')
40 	    GPSD_LOG(LOG_IO, &session->context->errout,
41 		     "<= GPS: %s\n", sentence);
42 	else
43 	    GPSD_LOG(LOG_IO, &session->context->errout,
44 		     "<= GPS: %s", sentence);
45 
46 	if ((st=nmea_parse(sentence, session)) == 0) {
47 	    GPSD_LOG(LOG_WARN, &session->context->errout,
48 		     "unknown sentence: \"%s\"\n", sentence);
49 	}
50 	for (dp = gpsd_drivers; *dp; dp++) {
51 	    char *trigger = (*dp)->trigger;
52 
53 	    if (trigger!=NULL && str_starts_with(sentence, trigger)) {
54 		GPSD_LOG(LOG_PROG, &session->context->errout,
55 			 "found trigger string %s.\n", trigger);
56 		if (*dp != session->device_type) {
57 		    (void)gpsd_switch_driver(session, (*dp)->type_name);
58 		    if (session->device_type != NULL
59 			&& session->device_type->event_hook != NULL)
60 			session->device_type->event_hook(session,
61 							 event_triggermatch);
62 		    st |= DEVICEID_SET;
63 		}
64 	    }
65 	}
66 	return st;
67 #endif /* NMEA0183_ENABLE */
68     } else {
69 	GPSD_LOG(LOG_SHOUT, &session->context->errout,
70 		 "packet type %d fell through (should never happen): %s.\n",
71 		 session->lexer.type, gpsd_prettydump(session));
72 	return 0;
73     }
74 }
75 
76 /**************************************************************************
77  *
78  * Generic driver -- make no assumptions about the device type
79  *
80  **************************************************************************/
81 
82 /* *INDENT-OFF* */
83 const struct gps_type_t driver_unknown = {
84     .type_name      = "Unknown",	/* full name of type */
85     .packet_type    = COMMENT_PACKET,	/* associated lexer packet type */
86     .flags	    = DRIVER_NOFLAGS,	/* no flags set */
87     .trigger	    = NULL,		/* it's the default */
88     .channels       = 12,		/* consumer-grade GPS */
89     .probe_detect   = NULL,		/* no probe */
90     .get_packet     = generic_get,	/* use generic packet getter */
91     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
92     .rtcm_writer    = NULL,		/* write RTCM data straight */
93     .init_query     = NULL,		/* non-perturbing initial query */
94     .event_hook     = NULL,		/* lifetime event handler */
95 #ifdef RECONFIGURE_ENABLE
96     .speed_switcher = NULL,		/* no speed switcher */
97     .mode_switcher  = NULL,		/* no mode switcher */
98     .rate_switcher  = NULL,		/* no sample-rate switcher */
99     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
100     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
101 #endif /* RECONFIGURE_ENABLE */
102 #ifdef CONTROLSEND_ENABLE
103     .control_send   = NULL,		/* how to send control strings */
104 #endif /* CONTROLSEND_ENABLE */
105     .time_offset     = NULL,		/* no method for NTP fudge factor */
106 };
107 /* *INDENT-ON* */
108 
109 #ifdef NMEA0183_ENABLE
110 /**************************************************************************
111  *
112  * NMEA 0183
113  *
114  * This is separate from the 'unknown' driver because we don't want to
115  * ship NMEA subtype probe strings to a device until we've seen at
116  * least one NMEA packet.  This avoids spamming devices that might
117  * actually be USB modems or other things in USB device class FF that
118  * just happen to have one of 'our' adaptor chips in front of them.
119  *
120  **************************************************************************/
121 
nmea_event_hook(struct gps_device_t * session,event_t event)122 static void nmea_event_hook(struct gps_device_t *session, event_t event)
123 {
124     if (session->context->readonly)
125 	return;
126     /*
127      * This is where we try to tickle NMEA devices into revealing their
128      * inner natures.
129      */
130     if (event == event_configure) {
131 	/*
132 	 * The reason for splitting these probes up by packet sequence
133 	 * number, interleaving them with the first few packet receives,
134 	 * is because many generic-NMEA devices get confused if you send
135 	 * too much at them in one go.
136 	 *
137 	 * A fast response to an early probe will change drivers so the
138 	 * later ones won't be sent at all.  Thus, for best overall
139 	 * performance, order these to probe for the most popular types
140 	 * soonest.
141 	 *
142 	 * Note: don't make the trigger strings identical to the probe,
143 	 * because some NMEA devices (notably SiRFs) will just echo
144 	 * unknown strings right back at you. A useful dodge is to append
145 	 * a comma to the trigger, because that won't be in the response
146 	 * unless there is actual following data.
147 	 */
148 	switch (session->lexer.counter) {
149 #ifdef NMEA0183_ENABLE
150 	case 0:
151 	    /* probe for Garmin serial GPS -- expect $PGRMC followed by data */
152 	    GPSD_LOG(LOG_PROG, &session->context->errout,
153 		     "=> Probing for Garmin NMEA\n");
154 	    (void)nmea_send(session, "$PGRMCE");
155 	    break;
156 #endif /* NMEA0183_ENABLE */
157 #ifdef SIRF_ENABLE
158 	case 1:
159 	    /*
160 	     * We used to try to probe for SiRF by issuing
161 	     * "$PSRF105,1" and expecting "$Ack Input105.".  But it
162 	     * turns out this only works for SiRF-IIs; SiRF-I and
163 	     * SiRF-III don't respond.  Sadly, the MID132 binary
164 	     * request for firmware version is ignored in NMEA mode.
165 	     * Thus the only reliable probe is to try to flip the SiRF
166 	     * into binary mode, cluing in the library to revert it on
167 	     * close.
168 	     *
169 	     * SiRFs dominate the consumer-grade GPS-mouse market, so
170 	     * we used to put this test first. Unfortunately this
171 	     * causes problems for gpsctl, as it cannot select the
172 	     * NMEA driver without switching the device back to binary
173 	     * mode!  Fix this if we ever find a nondisruptive probe
174 	     * string.
175 	     */
176 	    GPSD_LOG(LOG_PROG, &session->context->errout,
177 		     "=> Probing for SiRF\n");
178 	    (void)nmea_send(session,
179 			    "$PSRF100,0,%d,%d,%d,0",
180 			    session->gpsdata.dev.baudrate,
181 			    9 - session->gpsdata.dev.stopbits,
182 			    session->gpsdata.dev.stopbits);
183 	    break;
184 #endif /* SIRF_ENABLE */
185 #ifdef NMEA0183_ENABLE
186 	case 2:
187 	    /* probe for the FV-18 -- expect $PFEC,GPint followed by data */
188 	    GPSD_LOG(LOG_PROG, &session->context->errout,
189 		     "=> Probing for FV-18\n");
190 	    (void)nmea_send(session, "$PFEC,GPint");
191 	    break;
192 	case 3:
193 	    /* probe for the Trimble Copernicus */
194 	    GPSD_LOG(LOG_PROG, &session->context->errout,
195 		     "=> Probing for Trimble Copernicus\n");
196 	    (void)nmea_send(session, "$PTNLSNM,0139,01");
197 	    break;
198 #endif /* NMEA0183_ENABLE */
199 #ifdef EVERMORE_ENABLE
200 	case 4:
201 	    GPSD_LOG(LOG_PROG, &session->context->errout,
202 		     "=> Probing for Evermore\n");
203 	    /* Enable checksum and GGA(1s), GLL(0s), GSA(1s), GSV(1s), RMC(1s), VTG(0s), PEMT101(0s) */
204 	    /* EverMore will reply with: \x10\x02\x04\x38\x8E\xC6\x10\x03 */
205 	    (void)gpsd_write(session,
206 			     "\x10\x02\x12\x8E\x7F\x01\x01\x00\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x13\x10\x03",
207 			     22);
208 	    break;
209 #endif /* EVERMORE_ENABLE */
210 #ifdef GPSCLOCK_ENABLE
211 	case 5:
212 	    /* probe for Furuno Electric GH-79L4-N (GPSClock); expect $PFEC,GPssd */
213 	    GPSD_LOG(LOG_PROG, &session->context->errout,
214 		     "=> Probing for GPSClock\n");
215 	    (void)nmea_send(session, "$PFEC,GPsrq");
216 	    break;
217 #endif /* GPSCLOCK_ENABLE */
218 #ifdef ASHTECH_ENABLE
219 	case 6:
220 	    /* probe for Ashtech -- expect $PASHR,RID */
221 	    GPSD_LOG(LOG_PROG, &session->context->errout,
222 		     "=> Probing for Ashtech\n");
223 	    (void)nmea_send(session, "$PASHQ,RID");
224 	    break;
225 #endif /* ASHTECH_ENABLE */
226 #ifdef UBLOX_ENABLE
227 	case 7:
228 	    /* probe for UBX -- query port configuration */
229 	    GPSD_LOG(LOG_PROG, &session->context->errout,
230 		     "=> Probing for UBX\n");
231 	    (void)ubx_write(session, 0x06, 0x00, NULL, 0);
232 	    break;
233 #endif /* UBLOX_ENABLE */
234 #ifdef MTK3301_ENABLE
235 	case 8:
236 	    /* probe for MTK-3301 -- expect $PMTK705 */
237 	    GPSD_LOG(LOG_PROG, &session->context->errout,
238 		     "=> Probing for MediaTek\n");
239 	    (void)nmea_send(session, "$PMTK605");
240 	    break;
241 #endif /* MTK3301_ENABLE */
242 #ifdef GREIS_ENABLE
243 	case 9:
244 	    /* probe for Javad GREIS -- expect reply with JAVAD */
245 	    GPSD_LOG(LOG_PROG, &session->context->errout,
246 		     "=> Probing for Javad GREIS\n");
247 	    /* TODO: confirm this actually gets JAVAD response */
248 	    (void)nmea_send(session, "print,/par/rcv/vendor");
249 	    break;
250 #endif /* GREIS_ENABLE */
251 	default:
252 	    break;
253 	}
254     }
255 }
256 
257 /* *INDENT-OFF* */
258 const struct gps_type_t driver_nmea0183 = {
259     .type_name      = "NMEA0183",	/* full name of type */
260     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
261     .flags	    = DRIVER_NOFLAGS,	/* remember this */
262     .trigger	    = NULL,		/* it's the default */
263     .channels       = 12,		/* consumer-grade GPS */
264     .probe_detect   = NULL,		/* no probe */
265     .get_packet     = generic_get,	/* use generic packet getter */
266     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
267     .rtcm_writer    = gpsd_write,	/* write RTCM data straight */
268     .init_query     = NULL,		/* non-perturbing initial query */
269     .event_hook     = nmea_event_hook,	/* lifetime event handler */
270 #ifdef RECONFIGURE_ENABLE
271     .speed_switcher = NULL,		/* no speed switcher */
272 #ifdef BINARY_ENABLE
273     .mode_switcher  = NULL,		/* maybe switchable if it was a SiRF */
274 #else
275     .mode_switcher  = NULL,		/* no binary mode to revert to */
276 #endif /* BINARY_ENABLE */
277     .rate_switcher  = NULL,		/* no sample-rate switcher */
278     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
279     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
280 #endif /* RECONFIGURE_ENABLE */
281 #ifdef CONTROLSEND_ENABLE
282     .control_send   = nmea_write,	/* how to send control strings */
283 #endif /* CONTROLSEND_ENABLE */
284     .time_offset     = NULL,		/* no method for NTP fudge factor */
285 };
286 /* *INDENT-ON* */
287 
288 #if defined(GARMIN_ENABLE) && defined(NMEA0183_ENABLE)
289 /**************************************************************************
290  *
291  * Garmin NMEA
292  *
293  **************************************************************************/
294 
295 #ifdef RECONFIGURE_ENABLE
garmin_mode_switch(struct gps_device_t * session,int mode)296 static void garmin_mode_switch(struct gps_device_t *session, int mode)
297 /* only does anything in one direction, going to Garmin binary driver */
298 {
299     struct timespec delay;
300 
301     if (mode == MODE_BINARY) {
302 	(void)nmea_send(session, "$PGRMC1,1,2,1,,,,2,W,N");
303 	(void)nmea_send(session, "$PGRMI,,,,,,,R");
304         /* wait 333 uSec, standard Garmin settling time */
305 	delay.tv_sec = 0;
306 	delay.tv_nsec = 333000L;
307 	nanosleep(&delay, NULL);
308     }
309 }
310 #endif /* RECONFIGURE_ENABLE */
311 
garmin_nmea_event_hook(struct gps_device_t * session,event_t event)312 static void garmin_nmea_event_hook(struct gps_device_t *session,
313 				   event_t event)
314 {
315     if (session->context->readonly)
316 	return;
317 
318     if (event == event_driver_switch) {
319 	/* forces a reconfigure as the following packets come in */
320 	session->lexer.counter = 0;
321     }
322     if (event == event_configure) {
323 	/*
324 	 * And here's that reconfigure.  It's split up like this because
325 	 * receivers like the Garmin GPS-10 don't handle having having a lot of
326 	 * probes shoved at them very well.
327 	 */
328 	switch (session->lexer.counter) {
329 	case 0:
330 	    /* reset some config, AutoFix, WGS84, PPS
331 	     * Set the PPS pulse length to 40ms which leaves the Garmin 18-5hz
332 	     * with a 160ms low state.
333 	     * NOTE: new PPS only takes effect after next power cycle
334 	     */
335 	    (void)nmea_send(session, "$PGRMC,A,,100,,,,,,A,,1,2,1,30");
336 	    break;
337 	case 1:
338 	    /* once a sec, no averaging, NMEA 2.3, WAAS */
339 	    (void)nmea_send(session, "$PGRMC1,1,1,1,,,,2,W,N");
340 	    break;
341 	case 2:
342 	    /* get some more config info */
343 	    (void)nmea_send(session, "$PGRMC1E");
344 	    break;
345 	case 3:
346 	    /* turn off all output except GGA */
347 	    (void)nmea_send(session, "$PGRMO,,2");
348 	    (void)nmea_send(session, "$PGRMO,GPGGA,1");
349 	    break;
350 	case 4:
351 	    /* enable GPGGA, GPGSA, GPGSV, GPRMC on Garmin serial GPS */
352 	    (void)nmea_send(session, "$PGRMO,GPGSA,1");
353 	    break;
354 	case 5:
355 	    (void)nmea_send(session, "$PGRMO,GPGSV,1");
356 	    break;
357 	case 6:
358 	    (void)nmea_send(session, "$PGRMO,GPRMC,1");
359 	    break;
360 	case 7:
361 	    (void)nmea_send(session, "$PGRMO,PGRME,1");
362 	    break;
363 	}
364     }
365 }
366 
367 /* *INDENT-OFF* */
368 const struct gps_type_t driver_garmin = {
369     .type_name      = "Garmin NMEA",	/* full name of type */
370     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
371     .flags	    = DRIVER_STICKY,	/* remember this */
372     .trigger	    = "$PGRMC,",	/* Garmin private */
373     .channels       = 12,		/* not used by this driver */
374     .probe_detect   = NULL,		/* no probe */
375     .get_packet     = generic_get,	/* use generic packet getter */
376     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
377     .rtcm_writer    = NULL,		/* some do, some don't, skip for now */
378     .init_query     = NULL,		/* non-perturbing initial query */
379     .event_hook     = garmin_nmea_event_hook,	/* lifetime event handler */
380 #ifdef RECONFIGURE_ENABLE
381     .speed_switcher = NULL,			/* no speed switcher */
382     .mode_switcher  = garmin_mode_switch,	/* mode switcher */
383     .rate_switcher  = NULL,		/* no sample-rate switcher */
384     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
385     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
386 #endif /*RECONFIGURE_ENABLE */
387 #ifdef CONTROLSEND_ENABLE
388     .control_send   = nmea_write,	/* how to send control strings */
389 #endif /* CONTROLSEND_ENABLE */
390     .time_offset     = NULL,		/* no method for NTP fudge factor */
391 };
392 /* *INDENT-ON* */
393 #endif /* GARMIN_ENABLE && NMEA0183_ENABLE */
394 
395 #ifdef ASHTECH_ENABLE
396 /**************************************************************************
397  *
398  * Ashtech (then Thales, now Magellan Professional) Receivers
399  *
400  **************************************************************************/
401 
ashtech_event_hook(struct gps_device_t * session,event_t event)402 static void ashtech_event_hook(struct gps_device_t *session, event_t event)
403 {
404     if (session->context->readonly)
405 	return;
406 
407     if (event == event_wakeup)
408 	(void)nmea_send(session, "$PASHQ,RID");
409     if (event == event_identified) {
410 	/* turn WAAS on. can't hurt... */
411 	(void)nmea_send(session, "$PASHS,WAS,ON");
412 	/* reset to known output state */
413 	(void)nmea_send(session, "$PASHS,NME,ALL,A,OFF");
414 	/* then turn on some useful sentences */
415 #ifdef __future__
416 	/* we could parse these, but they're oversize so they get dropped */
417 	(void)nmea_send(session, "$PASHS,NME,POS,A,ON");
418 	(void)nmea_send(session, "$PASHS,NME,SAT,A,ON");
419 #else
420 	(void)nmea_send(session, "$PASHS,NME,GGA,A,ON");
421 	(void)nmea_send(session, "$PASHS,NME,GSA,A,ON");
422 	(void)nmea_send(session, "$PASHS,NME,GSV,A,ON");
423 	(void)nmea_send(session, "$PASHS,NME,RMC,A,ON");
424 #endif
425 	(void)nmea_send(session, "$PASHS,NME,ZDA,A,ON");
426     }
427 }
428 
429 /* *INDENT-OFF* */
430 const struct gps_type_t driver_ashtech = {
431     .type_name      = "Ashtech",	/* full name of type */
432     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
433     .flags	    = DRIVER_STICKY,	/* remember this */
434     .trigger	    = "$PASHR,RID,",	/* Ashtech receivers respond thus */
435     .channels       = 24,		/* not used, GG24 has 24 channels */
436     .probe_detect   = NULL,		/* no probe */
437     .get_packet     = generic_get,	/* how to get a packet */
438     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
439     .rtcm_writer    = gpsd_write,	/* write RTCM data straight */
440     .init_query     = NULL,		/* non-perturbing initial query */
441     .event_hook     = ashtech_event_hook, /* lifetime event handler */
442 #ifdef RECONFIGURE_ENABLE
443     .speed_switcher = NULL,		/* no speed switcher */
444     .mode_switcher  = NULL,		/* no mode switcher */
445     .rate_switcher  = NULL,		/* no sample-rate switcher */
446     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
447     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
448 #endif /* RECONFIGURE_ENABLE */
449 #ifdef CONTROLSEND_ENABLE
450     .control_send   = nmea_write,	/* how to send control strings */
451 #endif /* CONTROLSEND_ENABLE */
452     .time_offset     = NULL,		/* no method for NTP fudge factor */
453 };
454 /* *INDENT-ON* */
455 #endif /* ASHTECH_ENABLE */
456 
457 #ifdef FV18_ENABLE
458 /**************************************************************************
459  *
460  * FV18 -- uses 2 stop bits, needs to be told to send GSAs
461  *
462  **************************************************************************/
463 
fv18_event_hook(struct gps_device_t * session,event_t event)464 static void fv18_event_hook(struct gps_device_t *session, event_t event)
465 {
466     if (session->context->readonly)
467 	return;
468 
469     /*
470      * Tell an FV18 to send GSAs so we'll know if 3D is accurate.
471      * Suppress GLL and VTG.  Enable ZDA so dates will be accurate for replay.
472      * It's possible we might not need to redo this on event_reactivate,
473      * but doing so is safe and cheap.
474      */
475     if (event == event_identified || event == event_reactivate)
476 	(void)nmea_send(session,
477 			"$PFEC,GPint,GSA01,DTM00,ZDA01,RMC01,GLL00,VTG00,GSV05");
478 }
479 
480 /* *INDENT-OFF* */
481 const struct gps_type_t driver_fv18 = {
482     .type_name      = "San Jose Navigation FV18",	/* full name of type */
483     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
484     .flags	    = DRIVER_STICKY,	/* remember this */
485     .trigger	    = "$PFEC,GPint,",	/* FV18s should echo the probe */
486     .channels       = 12,		/* not used by this driver */
487     .probe_detect   = NULL,		/* no probe */
488     .get_packet     = generic_get,	/* how to get a packet */
489     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
490     .rtcm_writer    = gpsd_write,	/* write RTCM data straight */
491     .init_query     = NULL,		/* non-perturbing initial query */
492     .event_hook     = fv18_event_hook,	/* lifetime event handler */
493 #ifdef RECONFIGURE_ENABLE
494     .speed_switcher = NULL,		/* no speed switcher */
495     .mode_switcher  = NULL,		/* no mode switcher */
496     .rate_switcher  = NULL,		/* no sample-rate switcher */
497     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
498     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
499 #endif /* RECONFIGURE_ENABLE */
500 #ifdef CONTROLSEND_ENABLE
501     .control_send   = nmea_write,	/* how to send control strings */
502 #endif /* CONTROLSEND_ENABLE */
503     .time_offset     = NULL,		/* no method for NTP fudge factor */
504 };
505 /* *INDENT-ON* */
506 #endif /* FV18_ENABLE */
507 
508 #ifdef GPSCLOCK_ENABLE
509 /**************************************************************************
510  *
511  * Furuno Electric GPSClock (GH-79L4)
512  *
513  **************************************************************************/
514 
515 /*
516  * Based on http://www.tecsys.de/fileadmin/user_upload/pdf/gh79_1an_intant.pdf
517  */
518 
519 /* *INDENT-OFF* */
520 const struct gps_type_t driver_gpsclock = {
521     .type_name      = "Furuno Electric GH-79L4",	/* full name of type */
522     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
523     .flags	    = DRIVER_STICKY,	/* remember this */
524     .trigger	    = "$PFEC,GPssd",	/* GPSClock should return this */
525     .channels       = 12,		/* not used by this driver */
526     .probe_detect   = NULL,		/* no probe */
527     .get_packet     = generic_get,	/* how to get a packet */
528     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
529     .rtcm_writer    = gpsd_write,	/* write RTCM data straight */
530     .init_query     = NULL,		/* non-perturbing initial query */
531     .event_hook     = NULL,		/* no lifetime event handler */
532 #ifdef RECONFIGURE_ENABLE
533     .speed_switcher = NULL,		/* no speed switcher */
534     .mode_switcher  = NULL,		/* no mode switcher */
535     .rate_switcher  = NULL,		/* sample rate is fixed */
536     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
537     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
538 #endif /* RECONFIGURE_ENABLE */
539 #ifdef CONTROLSEND_ENABLE
540     .control_send   = nmea_write,	/* how to send control strings */
541 #endif /* CONTROLSEND_ENABLE */
542     .time_offset     = NULL,		/* no method for NTP fudge factor */
543 };
544 /* *INDENT-ON* */
545 #endif /* GPSCLOCK_ENABLE */
546 
547 #ifdef TRIPMATE_ENABLE
548 /**************************************************************************
549  *
550  * TripMate -- extended NMEA, gets faster fix when primed with lat/long/time
551  *
552  **************************************************************************/
553 
554 /*
555  * Some technical FAQs on the TripMate:
556  * http://vancouver-webpages.com/pub/peter/tripmate.faq
557  * http://www.asahi-net.or.jp/~KN6Y-GTU/tripmate/trmfaqe.html
558  * The TripMate was discontinued sometime before November 1998
559  * and was replaced by the Zodiac EarthMate.
560  */
561 
tripmate_event_hook(struct gps_device_t * session,event_t event)562 static void tripmate_event_hook(struct gps_device_t *session, event_t event)
563 {
564     if (session->context->readonly)
565 	return;
566     /* TripMate requires this response to the ASTRAL it sends at boot time */
567     if (event == event_identified)
568 	(void)nmea_send(session, "$IIGPQ,ASTRAL");
569     /* stop it sending PRWIZCH */
570     if (event == event_identified || event == event_reactivate)
571 	(void)nmea_send(session, "$PRWIILOG,ZCH,V,,");
572 }
573 
574 /* *INDENT-OFF* */
575 static const struct gps_type_t driver_tripmate = {
576     .type_name     = "Delorme TripMate",	/* full name of type */
577     .packet_type   = NMEA_PACKET,		/* lexer packet type */
578     .flags	   = DRIVER_STICKY,		/* no rollover or other flags */
579     .trigger       ="ASTRAL",			/* tells us to switch */
580     .channels      = 12,			/* consumer-grade GPS */
581     .probe_detect  = NULL,			/* no probe */
582     .get_packet    = generic_get,		/* how to get a packet */
583     .parse_packet  = generic_parse_input,	/* how to interpret a packet */
584     .rtcm_writer   = gpsd_write,		/* send RTCM data straight */
585     .init_query    = NULL,			/* non-perturbing query */
586     .event_hook    = tripmate_event_hook,	/* lifetime event handler */
587 #ifdef RECONFIGURE_ENABLE
588     .speed_switcher= NULL,			/* no speed switcher */
589     .mode_switcher = NULL,			/* no mode switcher */
590     .rate_switcher = NULL,			/* no sample-rate switcher */
591     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
592     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
593 #endif /* RECONFIGURE_ENABLE */
594 #ifdef CONTROLSEND_ENABLE
595     .control_send  = nmea_write,	/* how to send control strings */
596 #endif /* CONTROLSEND_ENABLE */
597     .time_offset     = NULL,		/* no method for NTP fudge factor */
598 };
599 /* *INDENT-ON* */
600 #endif /* TRIPMATE_ENABLE */
601 
602 #ifdef EARTHMATE_ENABLE
603 /**************************************************************************
604  *
605  * Zodiac EarthMate textual mode
606  *
607  * Note: This is the pre-2003 version using Zodiac binary protocol.
608  * There is a good HOWTO at <http://www.hamhud.net/ka9mva/earthmate.htm>.
609  * It has been replaced with a design that uses a SiRF chipset.
610  *
611  **************************************************************************/
612 
earthmate_event_hook(struct gps_device_t * session,event_t event)613 static void earthmate_event_hook(struct gps_device_t *session, event_t event)
614 {
615     struct timespec delay;
616 
617     if (session->context->readonly)
618 	return;
619     if (event == event_triggermatch) {
620 	(void)gpsd_write(session, "EARTHA\r\n", 8);
621         /* wait 10,000 uSec */
622 	delay.tv_sec = 0;
623 	delay.tv_nsec = 10000000L;
624 	nanosleep(&delay, NULL);
625 
626 	(void)gpsd_switch_driver(session, "Zodiac");
627     }
628 }
629 
630 /* *INDENT-OFF* */
631 static const struct gps_type_t driver_earthmate = {
632     .type_name     = "Pre-2003 Delorme EarthMate",
633     .packet_type   = NMEA_PACKET,	/* associated lexer packet type */
634     .flags	   = DRIVER_STICKY,		/* no rollover or other flags */
635     .trigger       = "EARTHA",			/* Earthmate trigger string */
636     .channels      = 12,			/* not used by NMEA parser */
637     .probe_detect  = NULL,			/* no probe */
638     .get_packet    = generic_get,		/* how to get a packet */
639     .parse_packet  = generic_parse_input,	/* how to interpret a packet */
640     .rtcm_writer   = NULL,			/* don't send RTCM data */
641     .init_query     = NULL,			/* non-perturbing query */
642     .event_hook    = earthmate_event_hook,	/* lifetime event handler */
643 #ifdef RECONFIGURE_ENABLE
644     .speed_switcher= NULL,			/* no speed switcher */
645     .mode_switcher = NULL,			/* no mode switcher */
646     .rate_switcher = NULL,			/* no sample-rate switcher */
647     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
648     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
649 #endif /* RECONFIGURE_ENABLE */
650 #ifdef CONTROLSEND_ENABLE
651     .control_send  = nmea_write,	/* never actually used. */
652 #endif /* CONTROLSEND_ENABLE */
653     .time_offset     = NULL,		/* no method for NTP fudge factor */
654 };
655 /* *INDENT-ON* */
656 #endif /* EARTHMATE_ENABLE */
657 
658 #endif /* NMEA0183_ENABLE */
659 
660 #ifdef TNT_ENABLE
661 /**************************************************************************
662  * True North Technologies - Revolution 2X Digital compass
663  *
664  * More info: http://www.tntc.com/
665  *
666  * This is a digital compass which uses magnetometers to measure the
667  * strength of the earth's magnetic field. Based on these measurements
668  * it provides a compass heading using NMEA formatted output strings.
669  * This is useful to supplement the heading provided by another GPS
670  * unit. A GPS heading is unreliable at slow speed or no speed.
671  *
672  **************************************************************************/
673 
tnt_control_send(struct gps_device_t * session,char * msg,size_t len UNUSED)674 static ssize_t tnt_control_send(struct gps_device_t *session,
675 				char *msg, size_t len UNUSED)
676 /* send a control string in TNT native formal */
677 {
678     ssize_t status;
679     unsigned char sum = '\0';
680     char c, *p = msg;
681 
682     if (*p == '@') {
683 	p++;
684     }
685 #ifdef __UNUSED__
686     else {
687 	GPSD_LOG(LOG_ERROR, &session->context->errout,
688 		 "Bad TNT sentence: '%s'\n", msg);
689     }
690 #endif /* __UNUSED__ */
691     while (((c = *p) != '\0')) {
692 	sum ^= c;
693 	p++;
694     }
695     (void)snprintf(p, 6, "*%02X\r\n", (unsigned int)sum);
696 
697     status = gpsd_write(session, msg, strlen(msg));
698     return status;
699 }
700 
tnt_send(struct gps_device_t * session,const char * fmt,...)701 static bool tnt_send(struct gps_device_t *session, const char *fmt, ...)
702 /* printf(3)-like TNT command generator */
703 {
704     char buf[BUFSIZ];
705     va_list ap;
706     ssize_t sent;
707 
708     va_start(ap, fmt);
709     (void)vsnprintf(buf, sizeof(buf) - 5, fmt, ap);
710     va_end(ap);
711     sent = tnt_control_send(session, buf, strlen(buf));
712     if (sent == (ssize_t) strlen(buf)) {
713 	GPSD_LOG(LOG_IO, &session->context->errout,
714 		 "=> GPS: %s\n", buf);
715 	return true;
716     } else {
717 	GPSD_LOG(LOG_WARN, &session->context->errout,
718 		 "=> GPS: %s FAILED\n", buf);
719 	return false;
720     }
721 }
722 
723 #ifdef RECONFIGURE_ENABLE
tnt_speed(struct gps_device_t * session,speed_t speed,char parity UNUSED,int stopbits UNUSED)724 static bool tnt_speed(struct gps_device_t *session,
725 		      speed_t speed, char parity UNUSED, int stopbits UNUSED)
726 {
727     /*
728      * Baud rate change followed by device reset.
729      * See page 40 of Technical Guide 1555-B.  We need:
730      * 2400 -> 1, 4800 -> 2, 9600 -> 3, 19200 -> 4, 38400 -> 5
731      */
732     unsigned int val = speed / 2400u;	/* 2400->1, 4800->2, 9600->4, 19200->8...  */
733     unsigned int i = 0;
734 
735     /* fast way to compute log2(val) */
736     while ((val >> i) > 1)
737 	++i;
738     return tnt_send(session, "@B6=%d", i + 1)
739 	&& tnt_send(session, "@F28.6=1");
740 }
741 #endif /* RECONFIGURE_ENABLE */
742 
tnt_event_hook(struct gps_device_t * session,event_t event)743 static void tnt_event_hook(struct gps_device_t *session, event_t event)
744 /* TNT lifetime event hook */
745 {
746     if (session->context->readonly)
747 	return;
748     if (event == event_wakeup) {
749 	(void)tnt_send(session, "@F0.3=1");	/* set run mode */
750 	(void)tnt_send(session, "@F2.2=1");	/* report in degrees */
751     }
752 }
753 
754 /* *INDENT-OFF* */
755 const struct gps_type_t driver_trueNorth = {
756     .type_name      = "True North",	/* full name of type */
757     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
758     .flags	    = DRIVER_STICKY,	/* remember this */
759     .trigger	    = "$PTNTHTM",	/* their proprietary sentence */
760     .channels       = 0,		/* not an actual GPS at all */
761     .probe_detect   = NULL,		/* no probe in run mode */
762     .get_packet     = generic_get,	/* how to get a packet */
763     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
764     .rtcm_writer    = NULL,		/* Don't send */
765     .init_query     = NULL,		/* non-perturbing initial query */
766     .event_hook     = tnt_event_hook,	/* lifetime event handler */
767 #ifdef RECONFIGURE_ENABLE
768     .speed_switcher = tnt_speed,	/* no speed switcher */
769     .mode_switcher  = NULL,		/* no mode switcher */
770     .rate_switcher  = NULL,		/* no wrapup */
771     .min_cycle.tv_sec  = 0,		/* not relevant, no rate switch */
772     .min_cycle.tv_nsec = 500000000,	/* not relevant, no rate switch */
773 #endif /* RECONFIGURE_ENABLE */
774 #ifdef CONTROLSEND_ENABLE
775     .control_send   = tnt_control_send,	/* how to send control strings */
776 #endif /* CONTROLSEND_ENABLE */
777     .time_offset     = NULL,
778 };
779 /* *INDENT-ON* */
780 #endif
781 
782 #ifdef OCEANSERVER_ENABLE
783 /**************************************************************************
784  * OceanServer - Digital Compass, OS5000 Series
785  *
786  * More info: http://www.ocean-server.com/download/OS5000_Compass_Manual.pdf
787  *
788  * This is a digital compass which uses magnetometers to measure the
789  * strength of the earth's magnetic field. Based on these measurements
790  * it provides a compass heading using NMEA formatted output strings.
791  * This is useful to supplement the heading provided by another GPS
792  * unit. A GPS heading is unreliable at slow speed or no speed.
793  *
794  **************************************************************************/
795 
oceanserver_send(struct gpsd_errout_t * errout,const int fd,const char * fmt,...)796 static int oceanserver_send(struct gpsd_errout_t *errout,
797 			    const int fd, const char *fmt, ...)
798 {
799     int status;
800     char buf[BUFSIZ];
801     va_list ap;
802 
803     va_start(ap, fmt);
804     (void)vsnprintf(buf, sizeof(buf) - 5, fmt, ap);
805     va_end(ap);
806     (void)strlcat(buf, "", sizeof(buf));
807     status = (int)write(fd, buf, strlen(buf));
808     (void)tcdrain(fd);
809     if (status == (int)strlen(buf)) {
810 	GPSD_LOG(LOG_IO, errout, "=> GPS: %s\n", buf);
811 	return status;
812     } else {
813 	GPSD_LOG(LOG_WARN, errout, "=> GPS: %s FAILED\n", buf);
814 	return -1;
815     }
816 }
817 
oceanserver_event_hook(struct gps_device_t * session,event_t event)818 static void oceanserver_event_hook(struct gps_device_t *session,
819 				   event_t event)
820 {
821     if (session->context->readonly)
822 	return;
823     if (event == event_configure && session->lexer.counter == 0) {
824 	/* report in NMEA format */
825 	(void)oceanserver_send(&session->context->errout,
826 			       session->gpsdata.gps_fd, "2\n");
827 	/* ship all fields */
828 	(void)oceanserver_send(&session->context->errout,
829 			       session->gpsdata.gps_fd, "X2047");
830     }
831 }
832 
833 /* *INDENT-OFF* */
834 static const struct gps_type_t driver_oceanServer = {
835     .type_name      = "OceanServer OS5000", /* full name of type */
836     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
837     .flags	    = DRIVER_STICKY,	/* no rollover or other flags */
838     .trigger	    = "$OHPR,",		/* detect their main sentence */
839     .channels       = 0,		/* not an actual GPS at all */
840     .probe_detect   = NULL,
841     .get_packet     = generic_get,	/* how to get a packet */
842     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
843     .rtcm_writer    = NULL,		/* Don't send */
844     .init_query     = NULL,		/* non-perturbing initial query */
845     .event_hook     = oceanserver_event_hook,
846 #ifdef RECONFIGURE_ENABLE
847     .speed_switcher = NULL,		/* no speed switcher */
848     .mode_switcher  = NULL,		/* no mode switcher */
849     .rate_switcher  = NULL,		/* no wrapup */
850     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
851     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
852 #endif /* RECONFIGURE_ENABLE */
853 #ifdef CONTROLSEND_ENABLE
854     .control_send   = nmea_write,	/* how to send control strings */
855 #endif /* CONTROLSEND_ENABLE */
856     .time_offset     = NULL,
857 };
858 /* *INDENT-ON* */
859 #endif
860 
861 #ifdef FURY_ENABLE
862 /**************************************************************************
863  *
864  * Jackson Labs Fury, a high-precision laboratory clock
865  *
866  * Will also support other Jackon Labs boards, including the Firefly.
867  *
868  * Note: you must either build with fixed_port_speed=115200 or tweak the
869  * speed on the port to 115200 before running.  The device's default mode
870  * does not stream output, so our hunt loop will simply time out otherwise.
871  *
872  **************************************************************************/
873 
fury_rate_switcher(struct gps_device_t * session,double rate)874 static bool fury_rate_switcher(struct gps_device_t *session, double rate)
875 {
876     char buf[78];
877     double inverted;
878 
879     /* rate is a frequency, but the command takes interval in # of seconds */
880     if (rate == 0.0)
881 	inverted = 0.0;
882     else
883 	inverted = 1.0/rate;
884     if (inverted > 256)
885 	return false;
886     (void)snprintf(buf, sizeof(buf), "GPS:GPGGA %d\r\n", (int)inverted);
887     (void)gpsd_write(session, buf, strlen(buf));
888     return true;
889 }
890 
fury_event_hook(struct gps_device_t * session,event_t event)891 static void fury_event_hook(struct gps_device_t *session, event_t event)
892 {
893     if (event == event_wakeup && gpsd_get_speed(session) == 115200)
894 	(void)fury_rate_switcher(session, 1.0);
895     else if (event == event_deactivate)
896 	(void)fury_rate_switcher(session, 0.0);
897 }
898 
899 
900 /* *INDENT-OFF* */
901 static const struct gps_type_t driver_fury = {
902     .type_name      = "Jackson Labs Fury", /* full name of type */
903     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
904     .flags	    = DRIVER_STICKY,	/* no rollover or other flags */
905     .trigger	    = NULL,		/* detect their main sentence */
906     .channels       = 0,		/* not an actual GPS at all */
907     .probe_detect   = NULL,
908     .get_packet     = generic_get,	/* how to get a packet */
909     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
910     .rtcm_writer    = NULL,		/* Don't send */
911     .init_query     = NULL,		/* non-perturbing initial query */
912     .event_hook     = fury_event_hook,
913 #ifdef RECONFIGURE_ENABLE
914     .speed_switcher = NULL,		/* no speed switcher */
915     .mode_switcher  = NULL,		/* no mode switcher */
916     .rate_switcher  = fury_rate_switcher,
917     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
918     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
919 #endif /* RECONFIGURE_ENABLE */
920 #ifdef CONTROLSEND_ENABLE
921     .control_send   = nmea_write,	/* how to send control strings */
922 #endif /* CONTROLSEND_ENABLE */
923     .time_offset     = NULL,
924 };
925 /* *INDENT-ON* */
926 
927 #endif /* FURY_ENABLE */
928 
929 #ifdef RTCM104V2_ENABLE
930 /**************************************************************************
931  *
932  * RTCM-104 (v2), used for broadcasting DGPS corrections and by DGPS radios
933  *
934  **************************************************************************/
935 
rtcm104v2_analyze(struct gps_device_t * session)936 static gps_mask_t rtcm104v2_analyze(struct gps_device_t *session)
937 {
938     rtcm2_unpack(&session->gpsdata.rtcm2, (char *)session->lexer.isgps.buf);
939     /* extra guard prevents expensive hexdump calls */
940     if (session->context->errout.debug >= LOG_RAW)
941 	GPSD_LOG(LOG_RAW, &session->context->errout,
942 		 "RTCM 2.x packet type 0x%02x length %d words "
943                  "from %zd bytes: %s\n",
944 		 session->gpsdata.rtcm2.type,
945 		 session->gpsdata.rtcm2.length + 2,
946 		 session->lexer.isgps.buflen,
947 		 gpsd_hexdump(session->msgbuf, sizeof(session->msgbuf),
948 				 (char *)session->lexer.isgps.buf,
949 				 (session->gpsdata.rtcm2.length +
950 				  2) * sizeof(isgps30bits_t)));
951     session->cycle_end_reliable = true;
952     return RTCM2_SET;
953 }
954 
955 /* *INDENT-OFF* */
956 static const struct gps_type_t driver_rtcm104v2 = {
957     .type_name     = "RTCM104V2",	/* full name of type */
958     .packet_type   = RTCM2_PACKET,	/* associated lexer packet type */
959     .flags	   = DRIVER_NOFLAGS,	/* no rollover or other flags */
960     .trigger       = NULL,		/* no recognition string */
961     .channels      = 0,			/* not used */
962     .probe_detect  = NULL,		/* no probe */
963     .get_packet    = generic_get,	/* how to get a packet */
964     .parse_packet  = rtcm104v2_analyze,	/*  */
965     .rtcm_writer   = NULL,		/* don't send RTCM data,  */
966     .init_query     = NULL,		/* non-perturbing initial query */
967     .event_hook    = NULL,		/* no event_hook */
968 #ifdef RECONFIGURE_ENABLE
969     .speed_switcher= NULL,		/* no speed switcher */
970     .mode_switcher = NULL,		/* no mode switcher */
971     .rate_switcher = NULL,		/* no sample-rate switcher */
972     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
973     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
974 #endif /* RECONFIGURE_ENABLE */
975 #ifdef CONTROLSEND_ENABLE
976     .control_send   = NULL,		/* how to send control strings */
977 #endif /* CONTROLSEND_ENABLE */
978     .time_offset     = NULL,
979 };
980 /* *INDENT-ON* */
981 #endif /* RTCM104V2_ENABLE */
982 #ifdef RTCM104V3_ENABLE
983 /**************************************************************************
984  *
985  * RTCM-104 (v3), used for broadcasting DGPS corrections and by DGPS radios
986  *
987  **************************************************************************/
988 
rtcm104v3_analyze(struct gps_device_t * session)989 static gps_mask_t rtcm104v3_analyze(struct gps_device_t *session)
990 {
991     uint16_t type = getbeu16(session->lexer.inbuffer, 3) >> 4;
992 
993     GPSD_LOG(LOG_RAW, &session->context->errout, "RTCM 3.x packet %d\n", type);
994     rtcm3_unpack(session->context,
995 		 &session->gpsdata.rtcm3,
996 		 (char *)session->lexer.outbuffer);
997     session->cycle_end_reliable = true;
998     return RTCM3_SET;
999 }
1000 
1001 /* *INDENT-OFF* */
1002 static const struct gps_type_t driver_rtcm104v3 = {
1003     .type_name     = "RTCM104V3",	/* full name of type */
1004     .packet_type   = RTCM3_PACKET,	/* associated lexer packet type */
1005     .flags	   = DRIVER_NOFLAGS,	/* no rollover or other flags */
1006     .trigger       = NULL,		/* no recognition string */
1007     .channels      = 0,			/* not used */
1008     .probe_detect  = NULL,		/* no probe */
1009     .get_packet    = generic_get,	/* how to get a packet */
1010     .parse_packet  = rtcm104v3_analyze,	/*  */
1011     .rtcm_writer   = NULL,		/* don't send RTCM data,  */
1012     .init_query    = NULL,		/* non-perturbing initial query */
1013     .event_hook    = NULL,		/* no event hook */
1014 #ifdef RECONFIGURE_ENABLE
1015     .speed_switcher= NULL,		/* no speed switcher */
1016     .mode_switcher = NULL,		/* no mode switcher */
1017     .rate_switcher = NULL,		/* no sample-rate switcher */
1018     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
1019     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
1020 #endif /* RECONFIGURE_ENABLE */
1021 #ifdef CONTROLSEND_ENABLE
1022     .control_send   = NULL,		/* how to send control strings */
1023 #endif /* CONTROLSEND_ENABLE */
1024     .time_offset     = NULL,
1025 };
1026 /* *INDENT-ON* */
1027 #endif /* RTCM104V3_ENABLE */
1028 
1029 #ifdef GARMINTXT_ENABLE
1030 /**************************************************************************
1031  *
1032  * Garmin Simple Text protocol
1033  *
1034  **************************************************************************/
1035 
1036 /* *INDENT-OFF* */
1037 static const struct gps_type_t driver_garmintxt = {
1038     .type_name     = "Garmin Simple Text",		/* full name of type */
1039     .packet_type   = GARMINTXT_PACKET,	/* associated lexer packet type */
1040     .flags	   = DRIVER_NOFLAGS,	/* no rollover or other flags */
1041     .trigger       = NULL,		/* no recognition string */
1042     .channels      = 0,			/* not used */
1043     .probe_detect  = NULL,		/* no probe */
1044     .get_packet    = generic_get,	/* how to get a packet */
1045     .parse_packet  = garmintxt_parse,	/* how to parse one */
1046     .rtcm_writer   = NULL,		/* don't send RTCM data,  */
1047     .init_query     = NULL,		/* non-perturbing initial query */
1048     .event_hook    = NULL,		/* no event hook */
1049 #ifdef RECONFIGURE_ENABLE
1050     .speed_switcher= NULL,		/* no speed switcher */
1051     .mode_switcher = NULL,		/* no mode switcher */
1052     .rate_switcher = NULL,		/* no sample-rate switcher */
1053     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
1054     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
1055 #endif /* RECONFIGURE_ENABLE */
1056 #ifdef CONTROLSEND_ENABLE
1057     .control_send   = NULL,		/* how to send control strings */
1058 #endif /* CONTROLSEND_ENABLE */
1059     .time_offset     = NULL,
1060 };
1061 /* *INDENT-ON* */
1062 #endif /* GARMINTXT_ENABLE */
1063 
1064 #ifdef MTK3301_ENABLE
1065 /**************************************************************************
1066  *
1067  * MediaTek MTK-3301, 3329, 3333, 3339
1068  *
1069  * OEMs for several GPS vendors, notably including Garmin, FasTrax, Trimble,
1070  * and AdaFruit. Website at <http://www.mediatek.com/>.
1071  *
1072  * The Trimble Condor appears to be an MTK3329.  It behaves as an MTK3301
1073  * and positively acknowledges all 3301 sentences as valid. It ignores $PMTK
1074  * sentence fields that are not implemented in the Trimble Condor. It does
1075  * not have power-save mode and ignores $PMTK320.  For $PMTK314 it silently
1076  * ignores periodic enabling of messages that aren't supported.
1077  *
1078  * From its datasheet the MTK3339 seems to add QZSS support not present in
1079  * earlier versions. The data sheet says it has 66 channels, which mkes
1080  * sense given the multi-constellation capability. The channel count
1081  * in the driver is never used by the NMEA driver so leaving the lower MTK3301
1082  * value in there is OK.
1083  *
1084  * MTK3333 support 10Hz.
1085  *
1086  * The Adafruit GPS HAT for the Raspberry Pi is an MTK3339. It works with this
1087  * driver; in fact AdaFruit's overview page for the product features GPSD.
1088  *
1089  **************************************************************************/
1090 
mtk3301_event_hook(struct gps_device_t * session,event_t event)1091 static void mtk3301_event_hook(struct gps_device_t *session, event_t event)
1092 {
1093 /*
1094 0  NMEA_SEN_GLL,  GPGLL   interval - Geographic Position - Latitude longitude
1095 1  NMEA_SEN_RMC,  GPRMC   interval - Recommended Minimum Specific GNSS Sentence
1096 2  NMEA_SEN_VTG,  GPVTG   interval - Course Over Ground and Ground Speed
1097 3  NMEA_SEN_GGA,  GPGGA   interval - GPS Fix Data
1098 4  NMEA_SEN_GSA,  GPGSA   interval - GNSS DOPS and Active Satellites
1099 5  NMEA_SEN_GSV,  GPGSV   interval - GNSS Satellites in View
1100 6  NMEA_SEN_GRS,  GPGRS   interval - GNSS Range Residuals
1101 7  NMEA_SEN_GST,  GPGST   interval - GNSS Pseudorange Errors Statistics
1102 13 NMEA_SEN_MALM, PMTKALM interval - GPS almanac information
1103 14 NMEA_SEN_MEPH, PMTKEPH interval - GPS ephemeris information
1104 15 NMEA_SEN_MDGP, PMTKDGP interval - GPS differential correction information
1105 16 NMEA_SEN_MDBG, PMTKDBG interval – MTK debug information
1106 17 NMEA_SEN_ZDA,  GPZDA   interval - Time & Date
1107 18 NMEA_SEN_MCHN, PMTKCHN interval – GPS channel status
1108 
1109 "$PMTK314,1,1,1,1,1,5,1,1,0,0,0,0,0,0,0,0,0,1,0"
1110 
1111 */
1112     if (session->context->readonly)
1113 	return;
1114     if (event == event_triggermatch) {
1115 	(void)nmea_send(session, "$PMTK320,0");	/* power save off */
1116 	(void)nmea_send(session, "$PMTK300,1000,0,0,0.0,0.0");/* Fix interval */
1117 	(void)nmea_send(session,
1118 			"$PMTK314,0,1,0,1,1,5,1,1,0,0,0,0,0,0,0,0,0,1,0");
1119 	(void)nmea_send(session, "$PMTK301,2");	/* DGPS is WAAS */
1120 	(void)nmea_send(session, "$PMTK313,1");	/* SBAS enable */
1121 
1122         /* PMTK_API_Q_OUTPUT_CTL - Query PPS pulse width - Trimble only?
1123          * http://trl.trimble.com/docushare/dsweb/Get/Document-482603/CONDOR_UG_2C_75263-00.pdf *
1124          * badly documented */
1125 	 (void)nmea_send(session, "$PMTK424");
1126     }
1127 }
1128 
1129 #ifdef RECONFIGURE_ENABLE
mtk3301_rate_switcher(struct gps_device_t * session,double rate)1130 static bool mtk3301_rate_switcher(struct gps_device_t *session, double rate)
1131 {
1132     char buf[78];
1133 
1134     unsigned int milliseconds = (unsigned int)(1000 * rate);
1135     if (rate > 1) {
1136         // force no slower than 1Hz
1137         milliseconds = 1000;
1138     } else if (rate < 0.1) {
1139         // force no faster than 10Hz, MTK3333 can do 10Hz
1140         milliseconds = 100;
1141     }
1142 
1143     (void)snprintf(buf, sizeof(buf), "$PMTK300,%u,0,0,0,0", milliseconds);
1144     (void)nmea_send(session, buf);	/* Fix interval */
1145     return true;
1146 }
1147 #endif /* RECONFIGURE_ENABLE */
1148 
1149 /* *INDENT-OFF* */
1150 const struct gps_type_t driver_mtk3301 = {
1151     .type_name      = "MTK-3301",	/* full name of type */
1152     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
1153     .flags	    = DRIVER_STICKY,	/* remember this */
1154     .trigger	    = "$PMTK705,",	/* firmware release name and version */
1155     .channels       = 12,		/* not used by this driver */
1156     .probe_detect   = NULL,		/* no probe */
1157     .get_packet     = generic_get,	/* how to get a packet */
1158     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
1159     .rtcm_writer    = gpsd_write,	/* write RTCM data straight */
1160     .init_query     = NULL,		/* non-perturbing initial query */
1161     .event_hook     = mtk3301_event_hook,	/* lifetime event handler */
1162 #ifdef RECONFIGURE_ENABLE
1163     .speed_switcher = NULL,		/* no speed switcher */
1164     .mode_switcher  = NULL,		/* no mode switcher */
1165     .rate_switcher  = mtk3301_rate_switcher,	/* sample rate switcher */
1166     .min_cycle.tv_sec  = 0,
1167     .min_cycle.tv_nsec = 100000000,     /* max 10Hz */
1168 #endif /* RECONFIGURE_ENABLE */
1169 #ifdef CONTROLSEND_ENABLE
1170     .control_send   = nmea_write,	/* how to send control strings */
1171 #endif /* CONTROLSEND_ENABLE */
1172     .time_offset     = NULL,
1173 };
1174 /* *INDENT-ON* */
1175 #endif /* MTK3301_ENABLE */
1176 
1177 #ifdef ISYNC_ENABLE
1178 /**************************************************************************
1179  *
1180  * Spectratime LNRCLOK / GRCLOK iSync GPS-disciplined rubidium oscillators
1181  *
1182  * These devices comprise a u-blox 6 attached to a separate iSync
1183  * microcontroller which drives the rubidium oscillator.  The iSync
1184  * microcontroller can be configured to pass through the underlying
1185  * GPS communication channel, while still using the GPS PPSREF signal
1186  * to discipline the rubidium oscillator.
1187  *
1188  * The iSync can also generate its own periodic status packets in NMEA
1189  * format.  These describe the state of the oscillator (including
1190  * whether or not the oscillator PPSOUT is synced to the GPS PPSREF).
1191  * These packets are transmitted in the middle of the underlying GPS
1192  * packets, forcing us to handle interrupted NMEA packets.
1193  *
1194  * The default state of the device is to generate no periodic output.
1195  * We send a probe string to initiate beating of the iSync-proprietary
1196  * $PTNTS,B message, which is then detected as a NMEA trigger.
1197  *
1198  **************************************************************************/
1199 
isync_write(struct gps_device_t * session,const char * data)1200 static ssize_t isync_write(struct gps_device_t *session, const char *data)
1201 
1202 {
1203     return gpsd_write(session, data, strlen(data));
1204 }
1205 
isync_detect(struct gps_device_t * session)1206 static bool isync_detect(struct gps_device_t *session)
1207 {
1208     speed_t old_baudrate;
1209     char old_parity;
1210     unsigned int old_stopbits;
1211 
1212     /* Set 9600 8N1 */
1213     old_baudrate = session->gpsdata.dev.baudrate;
1214     old_parity = session->gpsdata.dev.parity;
1215     old_stopbits = session->gpsdata.dev.stopbits;
1216     gpsd_set_speed(session, 9600, 'N', 1);
1217 
1218     /* Cancel pass-through mode and initiate beating of $PTNTS,B
1219      * message, which can subsequently be detected as a trigger.
1220      */
1221     (void)isync_write(session, "@@@@\r\nMAW0C0B\r\n");
1222 
1223     /* return serial port to original settings */
1224     gpsd_set_speed(session, old_baudrate, old_parity, old_stopbits);
1225 
1226     return false;
1227 }
1228 
isync_event_hook(struct gps_device_t * session,event_t event)1229 static void isync_event_hook(struct gps_device_t *session, event_t event)
1230 {
1231     if (session->context->readonly)
1232 	return;
1233 
1234     if (event == event_driver_switch) {
1235 	session->lexer.counter = 0;
1236     }
1237 
1238     if (event == event_configure) {
1239 	switch (session->lexer.counter) {
1240 	case 1:
1241 	    /* Configure timing and frequency flags:
1242 	     *  - Thermal compensation active
1243 	     *  - PPSREF active
1244 	     *  - PPSOUT active
1245 	     */
1246 	    (void)isync_write(session, "MAW040B\r\n");
1247 	    /* Configure tracking flags:
1248 	     *  - Save frequency every 24 hours
1249 	     *  - Align PPSOUT to PPSINT
1250 	     *  - Track PPSREF
1251 	     */
1252 	    (void)isync_write(session, "MAW0513\r\n");
1253 	    /* Configure tracking start flags:
1254 	     *  - Tracking restart allowed
1255 	     *  - Align to PPSREF
1256 	     */
1257 	    (void)isync_write(session, "MAW0606\r\n");
1258 	    /* Configure tracking window:
1259 	     *  - 4us
1260 	     */
1261 	    (void)isync_write(session, "MAW1304\r\n");
1262 	    /* Configure alarm window:
1263 	     *  - 4us
1264 	     */
1265 	    (void)isync_write(session, "MAW1404\r\n");
1266 	    break;
1267 	case 2:
1268 	    /* Configure pulse every d second:
1269 	     *  - pulse every second
1270 	     */
1271 	    (void)isync_write(session, "MAW1701\r\n");
1272 	    /* Configure pulse origin:
1273 	     *  - zero offset
1274 	     */
1275 	    (void)isync_write(session, "MAW1800\r\n");
1276 	    /* Configure pulse width:
1277 	     *  - 600ms
1278 	     */
1279 	    (void)isync_write(session, "MAW1223C34600\r\n");
1280 	    break;
1281 	case 3:
1282 	    /* Configure GPS resource utilization:
1283 	     *  - do not consider GPS messages
1284 	     */
1285 	    (void)isync_write(session, "MAW2200\r\n");
1286 	    /* Restart sync */
1287 	    (void)isync_write(session, "SY1\r\n");
1288 	    /* Restart tracking */
1289 	    (void)isync_write(session, "TR1\r\n");
1290 	    break;
1291 	case 4:
1292 	    /* Cancel BTx messages (if any) */
1293 	    (void)isync_write(session, "BT0\r\n");
1294 	    /* Configure messages coming out every second:
1295 	     *  - Oscillator status ($PTNTA) at 750ms
1296 	     */
1297 	    (void)isync_write(session, "MAW0B00\r\n");
1298 	    (void)isync_write(session, "MAW0C0A\r\n");
1299 	    break;
1300 	case 5:
1301 	    /* Enable GPS passthrough and force u-blox driver to
1302 	     * select NMEA mode.
1303 	     */
1304 	    session->mode = 0;
1305 	    session->drivers_identified = 0;
1306 	    (void)isync_write(session, "@@@@GPS\r\n");
1307 	    break;
1308 	case 6:
1309 	    /* Trigger detection of underlying u-blox (if necessary) */
1310 	    (void)ubx_write(session, 0x06, 0x00, NULL, 0);
1311 	    break;
1312 	}
1313     }
1314 }
1315 
1316 /* *INDENT-OFF* */
1317 const struct gps_type_t driver_isync = {
1318     .type_name      = "iSync",		/* full name of type */
1319     .packet_type    = NMEA_PACKET,	/* associated lexer packet type */
1320     .flags          = DRIVER_STICKY,	/* remember this */
1321     .trigger	    = "$PTNTS,B,",	/* iSync status message */
1322     .channels       = 50,		/* copied from driver_ubx */
1323     .probe_detect   = isync_detect,	/* how to detect at startup time */
1324     .get_packet     = generic_get,	/* how to get a packet */
1325     .parse_packet   = generic_parse_input,	/* how to interpret a packet */
1326     .init_query     = NULL,		/* non-perturbing initial query */
1327     .event_hook     = isync_event_hook,	/* lifetime event handler */
1328 #ifdef RECONFIGURE_ENABLE
1329     .speed_switcher = NULL,		/* no speed switcher */
1330     .mode_switcher  = NULL,		/* no mode switcher */
1331     .rate_switcher  = NULL,		/* no sample-rate switcher */
1332     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
1333     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
1334 #endif /* RECONFIGURE_ENABLE */
1335 #ifdef CONTROLSEND_ENABLE
1336     .control_send   = nmea_write,	/* how to send control strings */
1337 #endif /* CONTROLSEND_ENABLE */
1338     .time_offset     = NULL,		/* no method for NTP fudge factor */
1339 };
1340 /* *INDENT-ON* */
1341 #endif /* ISYNC_ENABLE */
1342 
1343 #ifdef AIVDM_ENABLE
1344 /**************************************************************************
1345  *
1346  * AIVDM - ASCII armoring of binary AIS packets
1347  *
1348  **************************************************************************/
1349 
aivdm_decode(const char * buf,size_t buflen,struct gps_device_t * session,struct ais_t * ais,int debug)1350 static bool aivdm_decode(const char *buf, size_t buflen,
1351 		  struct gps_device_t *session,
1352 		  struct ais_t *ais,
1353 		  int debug)
1354 {
1355 #ifdef __UNUSED_DEBUG__
1356     char *sixbits[64] = {
1357 	"000000", "000001", "000010", "000011", "000100",
1358 	"000101", "000110", "000111", "001000", "001001",
1359 	"001010", "001011", "001100", "001101", "001110",
1360 	"001111", "010000", "010001", "010010", "010011",
1361 	"010100", "010101", "010110", "010111", "011000",
1362 	"011001", "011010", "011011", "011100", "011101",
1363 	"011110", "011111", "100000", "100001", "100010",
1364 	"100011", "100100", "100101", "100110", "100111",
1365 	"101000", "101001", "101010", "101011", "101100",
1366 	"101101", "101110", "101111", "110000", "110001",
1367 	"110010", "110011", "110100", "110101", "110110",
1368 	"110111", "111000", "111001", "111010", "111011",
1369 	"111100", "111101", "111110", "111111",
1370     };
1371 #endif /* __UNUSED_DEBUG__ */
1372     int nfrags, ifrag, nfields = 0;
1373     unsigned char *field[NMEA_MAX*2];
1374     unsigned char fieldcopy[NMEA_MAX*2+1];
1375     unsigned char *data, *cp;
1376     char const *cp1;
1377     int pad;
1378     struct aivdm_context_t *ais_context;
1379     int i;
1380 
1381     if (buflen == 0)
1382 	return false;
1383 
1384     /* we may need to dump the raw packet */
1385     GPSD_LOG(LOG_PROG, &session->context->errout,
1386 	     "AIVDM packet length %zd: %s\n", buflen, buf);
1387 
1388     /* first clear the result, making sure we don't return garbage */
1389     memset(ais, 0, sizeof(*ais));
1390 
1391     /* discard overlong sentences */
1392     if (strlen(buf) > sizeof(fieldcopy)-1) {
1393 	GPSD_LOG(LOG_ERROR, &session->context->errout,
1394 		 "overlong AIVDM packet.\n");
1395 	return false;
1396     }
1397 
1398     /* discard sentences with high-half characters in them, they're corrupted */
1399     for (cp1 = buf; *cp1; cp1++) {
1400 	if (!isascii(*cp1)) {
1401 	    GPSD_LOG(LOG_ERROR, &session->context->errout,
1402 		     "corrupted AIVDM packet.\n");
1403 	    return false;
1404 	}
1405     }
1406 
1407     /* extract packet fields */
1408     (void)strlcpy((char *)fieldcopy, buf, sizeof(fieldcopy));
1409     field[nfields++] = (unsigned char *)buf;
1410     for (cp = fieldcopy;
1411 	 cp < fieldcopy + buflen; cp++)
1412     {
1413 	if (
1414              (*cp == (unsigned char)',') ||
1415              (*cp == (unsigned char)'*')
1416            ) {
1417 	    *cp = '\0';
1418 	    field[nfields++] = cp + 1;
1419 	}
1420     }
1421 #ifdef __UNDEF_DEBUG_
1422     for(int i=0;i<nfields;i++)
1423         GPSD_LOG(LOG_DATA, &session->context->errout,
1424                  "field [%d] [%s]\n", i, field[i]);
1425 #endif
1426 
1427     /* discard sentences with exiguous commas; catches run-ons */
1428     if (nfields < 7) {
1429 	GPSD_LOG(LOG_ERROR, &session->context->errout,
1430 		 "malformed AIVDM packet.\n");
1431 	return false;
1432     }
1433 
1434     switch (field[4][0]) {
1435     case '\0':
1436 	/*
1437 	 * Apparently an empty channel is normal for AIVDO sentences,
1438 	 * which makes sense as they don't come in over radio.  This
1439 	 * is going to break if there's ever an AIVDO type 24, though.
1440 	 */
1441 	if (!str_starts_with((const char *)field[0], "!AIVDO"))
1442 	    GPSD_LOG(LOG_INF, &session->context->errout,
1443 		     "invalid empty AIS channel. Assuming 'A'\n");
1444 	ais_context = &session->driver.aivdm.context[0];
1445 	session->driver.aivdm.ais_channel ='A';
1446 	break;
1447     case '1':
1448 	if (strcmp((char *)field[4], (char *)"12") == 0) {
1449 	    GPSD_LOG(LOG_INF, &session->context->errout,
1450 		     "ignoring bogus AIS channel '12'.\n");
1451 	    return false;
1452 	}
1453 	/* fall through */
1454     case 'A':
1455 	ais_context = &session->driver.aivdm.context[0];
1456 	session->driver.aivdm.ais_channel ='A';
1457 	break;
1458     case '2':
1459     case 'B':
1460 	ais_context = &session->driver.aivdm.context[1];
1461 	session->driver.aivdm.ais_channel ='B';
1462 	break;
1463     case 'C':
1464         GPSD_LOG(LOG_INF, &session->context->errout,
1465 		 "ignoring AIS channel C (secure AIS).\n");
1466         return false;
1467     default:
1468 	GPSD_LOG(LOG_ERROR, &session->context->errout,
1469 		 "invalid AIS channel 0x%0X .\n", field[4][0]);
1470 	return false;
1471     }
1472 
1473     nfrags = atoi((char *)field[1]); /* number of fragments to expect */
1474     ifrag = atoi((char *)field[2]); /* fragment id */
1475     data = field[5];
1476 
1477     pad = 0;
1478     if(isdigit(field[6][0]))
1479         pad = field[6][0] - '0'; /* number of padding bits ASCII encoded*/
1480     GPSD_LOG(LOG_PROG, &session->context->errout,
1481 	     "nfrags=%d, ifrag=%d, decoded_frags=%d, data=%s, pad=%d\n",
1482 	     nfrags, ifrag, ais_context->decoded_frags, data, pad);
1483 
1484     /* assemble the binary data */
1485 
1486     /* check fragment ordering */
1487     if (ifrag != ais_context->decoded_frags + 1) {
1488 	GPSD_LOG(LOG_ERROR, &session->context->errout,
1489 		 "invalid fragment #%d received, expected #%d.\n",
1490 		 ifrag, ais_context->decoded_frags + 1);
1491 	if (ifrag != 1)
1492 	    return false;
1493         /* else, ifrag==1: Just discard all that was previously decoded and
1494          * simply handle that packet */
1495         ais_context->decoded_frags = 0;
1496     }
1497     if (ifrag == 1) {
1498 	(void)memset(ais_context->bits, '\0', sizeof(ais_context->bits));
1499 	ais_context->bitlen = 0;
1500     }
1501 
1502     /* wacky 6-bit encoding, shades of FIELDATA */
1503     for (cp = data; cp < data + strlen((char *)data); cp++) {
1504 	unsigned char ch;
1505 	ch = *cp;
1506 	ch -= 48;
1507 	if (ch >= 40)
1508 	    ch -= 8;
1509 #ifdef __UNUSED_DEBUG__
1510 	GPSD_LOG(LOG_RAW, &session->context->errout,
1511 		 "%c: %s\n", *cp, sixbits[ch]);
1512 #endif /* __UNUSED_DEBUG__ */
1513 	for (i = 5; i >= 0; i--) {
1514 	    if ((ch >> i) & 0x01) {
1515 		ais_context->bits[ais_context->bitlen / 8] |=
1516 		    (1 << (7 - ais_context->bitlen % 8));
1517 	    }
1518 	    ais_context->bitlen++;
1519 	    if (ais_context->bitlen > sizeof(ais_context->bits)) {
1520 		GPSD_LOG(LOG_INF, &session->context->errout,
1521 			 "overlong AIVDM payload truncated.\n");
1522 		return false;
1523 	    }
1524 	}
1525     }
1526     ais_context->bitlen -= pad;
1527 
1528     /* time to pass buffered-up data to where it's actually processed? */
1529     if (ifrag == nfrags) {
1530 	if (debug >= LOG_INF) {
1531 	    size_t clen = BITS_TO_BYTES(ais_context->bitlen);
1532 	    GPSD_LOG(LOG_INF, &session->context->errout,
1533 		     "AIVDM payload is %zd bits, %zd chars: %s\n",
1534 		     ais_context->bitlen, clen,
1535 		     gpsd_hexdump(session->msgbuf, sizeof(session->msgbuf),
1536 				     (char *)ais_context->bits, clen));
1537 	}
1538 
1539         /* clear waiting fragments count */
1540         ais_context->decoded_frags = 0;
1541 
1542 	/* decode the assembled binary packet */
1543 	return ais_binary_decode(&session->context->errout,
1544 				 ais,
1545 				 ais_context->bits,
1546 				 ais_context->bitlen,
1547 				 &ais_context->type24_queue);
1548     }
1549 
1550     /* we're still waiting on another sentence */
1551     ais_context->decoded_frags++;
1552     return false;
1553 }
1554 
aivdm_analyze(struct gps_device_t * session)1555 static gps_mask_t aivdm_analyze(struct gps_device_t *session)
1556 {
1557     if (session->lexer.type == AIVDM_PACKET) {
1558 	if (aivdm_decode
1559 	    ((char *)session->lexer.outbuffer, session->lexer.outbuflen,
1560 	     session, &session->gpsdata.ais,
1561 	     session->context->errout.debug)) {
1562 	    return ONLINE_SET | AIS_SET;
1563 	} else
1564 	    return ONLINE_SET;
1565 #ifdef NMEA0183_ENABLE
1566     } else if (session->lexer.type == NMEA_PACKET) {
1567 	return nmea_parse((char *)session->lexer.outbuffer, session);
1568 #endif /* NMEA0183_ENABLE */
1569     } else
1570 	return 0;
1571 }
1572 
1573 /* *INDENT-OFF* */
1574 const struct gps_type_t driver_aivdm = {
1575     /* Full name of type */
1576     .type_name        = "AIVDM",    	/* associated lexer packet type */
1577     .packet_type      = AIVDM_PACKET,	/* numeric packet type */
1578     .flags	      = DRIVER_NOFLAGS,	/* no rollover or other flags */
1579     .trigger          = NULL,		/* identifying response */
1580     .channels         = 0,		/* not used by this driver */
1581     .probe_detect     = NULL,		/* no probe */
1582     .get_packet       = generic_get,	/* how to get a packet */
1583     .parse_packet     = aivdm_analyze,	/* how to analyze a packet */
1584     .rtcm_writer      = NULL,		/* don't send RTCM data,  */
1585     .init_query       = NULL,		/* non-perturbing initial query */
1586     .event_hook       = NULL,		/* lifetime event handler */
1587 #ifdef RECONFIGURE_ENABLE
1588     .speed_switcher   = NULL,		/* no speed switcher */
1589     .mode_switcher    = NULL,		/* no mode switcher */
1590     .rate_switcher    = NULL,		/* no rate switcher */
1591     .min_cycle.tv_sec  = 1,		/* max 1Hz */
1592     .min_cycle.tv_nsec = 0,
1593 #endif /* RECONFIGURE_ENABLE */
1594 #ifdef CONTROLSEND_ENABLE
1595     .control_send     = NULL,		/* no control sender */
1596 #endif /* CONTROLSEND_ENABLE */
1597     .time_offset     = NULL,		/* no NTP communication */
1598 };
1599 /* *INDENT-ON* */
1600 #endif /* AIVDM_ENABLE */
1601 
1602 #ifdef PASSTHROUGH_ENABLE
1603 /**************************************************************************
1604  *
1605  * JSON passthrough driver
1606  *
1607  **************************************************************************/
1608 
path_rewrite(struct gps_device_t * session,char * prefix)1609 static void path_rewrite(struct gps_device_t *session, char *prefix)
1610 /* prepend the session path to the value of a specified attribute */
1611 {
1612     /*
1613      * Hack the packet to reflect its origin.  This code is supposed
1614      * to insert the path naming the remote gpsd instance into the
1615      * beginning of the path attribute, followed by a # to separate it
1616      * from the device.
1617      */
1618     char *prefloc;
1619 
1620     assert(prefix != NULL && session->lexer.outbuffer != NULL);
1621 
1622     /* possibly the rewrite has been done already, this comw up in gpsmon */
1623     if (strstr((char *)session->lexer.outbuffer, session->gpsdata.dev.path) != NULL)
1624 	return;
1625 
1626     for (prefloc = (char *)session->lexer.outbuffer;
1627 	 prefloc < (char *)session->lexer.outbuffer+session->lexer.outbuflen;
1628 	 prefloc++)
1629 	if (str_starts_with(prefloc, prefix)) {
1630 	    char *sfxloc;
1631 	    char copy[sizeof(session->lexer.outbuffer)+1];
1632 	    (void)strlcpy(copy,
1633 			  (char *)session->lexer.outbuffer,
1634 			  sizeof(copy));
1635 	    prefloc += strlen(prefix);
1636 	    (void)strlcpy(prefloc,
1637 			  session->gpsdata.dev.path,
1638 			  sizeof(session->gpsdata.dev.path));
1639 	    if ((sfxloc = strchr(prefloc, '#')))
1640 		*sfxloc = '\0';  /* Avoid accumulating multiple device names */
1641 	    (void)strlcat((char *)session->lexer.outbuffer, "#",
1642 			  sizeof(session->lexer.outbuffer));
1643 	    (void)strlcat((char *)session->lexer.outbuffer,
1644 			  copy + (prefloc-(char *)session->lexer.outbuffer),
1645 			  sizeof(session->lexer.outbuffer));
1646 	}
1647     session->lexer.outbuflen = strlen((char *)session->lexer.outbuffer);
1648 }
1649 
json_pass_packet(struct gps_device_t * session)1650 static gps_mask_t json_pass_packet(struct gps_device_t *session)
1651 {
1652     GPSD_LOG(LOG_IO, &session->context->errout,
1653 	     "<= GPS: %s\n", (char *)session->lexer.outbuffer);
1654 
1655     if (strstr(session->gpsdata.dev.path, ":/") != NULL && strstr(session->gpsdata.dev.path, "localhost") == NULL)
1656     {
1657 	/* devices and paths need to be edited */
1658 	if (strstr((char *)session->lexer.outbuffer, "DEVICE") != NULL)
1659 	    path_rewrite(session, "\"path\":\"");
1660 	path_rewrite(session, "\"device\":\"");
1661 
1662 	/* mark certain responses without a path or device attribute */
1663 	if (session->gpsdata.dev.path[0] != '\0') {
1664 	    if (strstr((char *)session->lexer.outbuffer, "VERSION") != NULL
1665 		|| strstr((char *)session->lexer.outbuffer, "WATCH") != NULL
1666 		|| strstr((char *)session->lexer.outbuffer, "DEVICES") != NULL) {
1667 		session->lexer.outbuffer[session->lexer.outbuflen-1] = '\0';
1668 		(void)strlcat((char *)session->lexer.outbuffer, ",\"remote\":\"",
1669 			      sizeof(session->lexer.outbuffer));
1670 		(void)strlcat((char *)session->lexer.outbuffer,
1671 			      session->gpsdata.dev.path,
1672 			      sizeof(session->lexer.outbuffer));
1673 		(void)strlcat((char *)session->lexer.outbuffer, "\"}",
1674 			      sizeof(session->lexer.outbuffer));
1675 	    }
1676 	    session->lexer.outbuflen = strlen((char *)session->lexer.outbuffer);
1677 	}
1678     }
1679     GPSD_LOG(LOG_PROG, &session->context->errout,
1680 	     "JSON, passing through %s\n",
1681 	     (char *)session->lexer.outbuffer);
1682     return PASSTHROUGH_IS;
1683 }
1684 
1685 /* *INDENT-OFF* */
1686 const struct gps_type_t driver_json_passthrough = {
1687     .type_name      = "JSON slave driver",	/* full name of type */
1688     .packet_type    = JSON_PACKET,	/* associated lexer packet type */
1689     .flags	    = DRIVER_NOFLAGS,	/* don't remember this */
1690     .trigger	    = NULL,		/* it's the default */
1691     .channels       = 0,		/* not used */
1692     .probe_detect   = NULL,		/* no probe */
1693     .get_packet     = generic_get,	/* use generic packet getter */
1694     .parse_packet   = json_pass_packet,	/* how to interpret a packet */
1695     .rtcm_writer    = NULL,		/* write RTCM data straight */
1696     .init_query     = NULL,		/* non-perturbing initial query */
1697     .event_hook     = NULL,		/* lifetime event handler */
1698 #ifdef RECONFIGURE_ENABLE
1699     .speed_switcher = NULL,		/* no speed switcher */
1700     .mode_switcher  = NULL,		/* no mode switcher */
1701     .rate_switcher  = NULL,		/* no sample-rate switcher */
1702     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
1703     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
1704 #endif /* RECONFIGURE_ENABLE */
1705 #ifdef CONTROLSEND_ENABLE
1706     .control_send   = NULL,		/* how to send control strings */
1707 #endif /* CONTROLSEND_ENABLE */
1708     .time_offset     = NULL,		/* no method for NTP fudge factor */
1709 };
1710 /* *INDENT-ON* */
1711 
1712 #endif /* PASSTHROUGH_ENABLE */
1713 
1714 /* *INDENT-OFF* */
1715 const struct gps_type_t driver_pps = {
1716     .type_name      = "PPS",		/* full name of type */
1717     .packet_type    = BAD_PACKET,	/* associated lexer packet type */
1718     .flags	    = DRIVER_NOFLAGS,	/* don't remember this */
1719     .trigger	    = NULL,		/* it's the default */
1720     .channels       = 0,		/* not used */
1721     .probe_detect   = NULL,		/* no probe */
1722     .get_packet     = NULL,		/* use generic packet getter */
1723     .parse_packet   = NULL,		/* how to interpret a packet */
1724     .rtcm_writer    = NULL,		/* write RTCM data straight */
1725     .init_query     = NULL,		/* non-perturbing initial query */
1726     .event_hook     = NULL,		/* lifetime event handler */
1727 #ifdef RECONFIGURE_ENABLE
1728     .speed_switcher = NULL,		/* no speed switcher */
1729     .mode_switcher  = NULL,		/* no mode switcher */
1730     .rate_switcher  = NULL,		/* no sample-rate switcher */
1731     .min_cycle.tv_sec  = 1,		/* not relevant, no rate switch */
1732     .min_cycle.tv_nsec = 0,		/* not relevant, no rate switch */
1733 #endif /* RECONFIGURE_ENABLE */
1734 #ifdef CONTROLSEND_ENABLE
1735     .control_send   = NULL,		/* how to send control strings */
1736 #endif /* CONTROLSEND_ENABLE */
1737     .time_offset     = NULL,		/* no method for NTP fudge factor */
1738 };
1739 /* *INDENT-ON* */
1740 
1741 
1742 extern const struct gps_type_t driver_evermore;
1743 extern const struct gps_type_t driver_garmin_ser_binary;
1744 extern const struct gps_type_t driver_garmin_usb_binary;
1745 extern const struct gps_type_t driver_geostar;
1746 extern const struct gps_type_t driver_greis;
1747 extern const struct gps_type_t driver_italk;
1748 extern const struct gps_type_t driver_navcom;
1749 extern const struct gps_type_t driver_nmea2000;
1750 extern const struct gps_type_t driver_oncore;
1751 extern const struct gps_type_t driver_sirf;
1752 extern const struct gps_type_t driver_skytraq;
1753 extern const struct gps_type_t driver_superstar2;
1754 extern const struct gps_type_t driver_tsip;
1755 extern const struct gps_type_t driver_ubx;
1756 extern const struct gps_type_t driver_zodiac;
1757 
1758 /* the point of this rigamarole is to not have to export a table size */
1759 static const struct gps_type_t *gpsd_driver_array[] = {
1760     &driver_unknown,
1761 #ifdef NMEA0183_ENABLE
1762     &driver_nmea0183,
1763 #ifdef ASHTECH_ENABLE
1764     &driver_ashtech,
1765 #endif /* ASHTECH_ENABLE */
1766 #ifdef TRIPMATE_ENABLE
1767     &driver_tripmate,
1768 #endif /* TRIPMATE_ENABLE */
1769 #ifdef EARTHMATE_ENABLE
1770     &driver_earthmate,
1771 #endif /* EARTHMATE_ENABLE */
1772 #ifdef GPSCLOCK_ENABLE
1773     &driver_gpsclock,
1774 #endif /* GPSCLOCK_ENABLE */
1775 #ifdef GARMIN_ENABLE
1776     &driver_garmin,
1777 #endif /* GARMIN_ENABLE */
1778 #ifdef MTK3301_ENABLE
1779     &driver_mtk3301,
1780 #endif /*  MTK3301_ENABLE */
1781 #ifdef OCEANSERVER_ENABLE
1782     &driver_oceanServer,
1783 #endif /* OCEANSERVER_ENABLE */
1784 #ifdef FV18_ENABLE
1785     &driver_fv18,
1786 #endif /* FV18_ENABLE */
1787 #ifdef TNT_ENABLE
1788     &driver_trueNorth,
1789 #endif /* TNT_ENABLE */
1790 #ifdef FURY_ENABLE
1791     &driver_fury,
1792 #endif /* FURY_ENABLE */
1793 #ifdef AIVDM_ENABLE
1794     &driver_aivdm,
1795 #endif /* AIVDM_ENABLE */
1796 #endif /* NMEA0183_ENABLE */
1797 
1798 #ifdef EVERMORE_ENABLE
1799     &driver_evermore,
1800 #endif /* EVERMORE_ENABLE */
1801 #ifdef GARMIN_ENABLE
1802     /* be sure to try Garmin Serial Binary before Garmin USB Binary */
1803     &driver_garmin_ser_binary,
1804     &driver_garmin_usb_binary,
1805 #endif /* GARMIN_ENABLE */
1806 #ifdef GEOSTAR_ENABLE
1807     &driver_geostar,
1808 #endif /* GEOSTAR_ENABLE */
1809 #ifdef GREIS_ENABLE
1810     &driver_greis,
1811 #endif /* GREIS_ENABLE */
1812 #ifdef ITRAX_ENABLE
1813     &driver_italk,
1814 #endif /* ITRAX_ENABLE */
1815 #ifdef ONCORE_ENABLE
1816     &driver_oncore,
1817 #endif /* ONCORE_ENABLE */
1818 #ifdef NAVCOM_ENABLE
1819     &driver_navcom,
1820 #endif /* NAVCOM_ENABLE */
1821 #ifdef SIRF_ENABLE
1822     &driver_sirf,
1823 #endif /* SIRF_ENABLE */
1824 #ifdef SKYTRAQ_ENABLE
1825     &driver_skytraq,
1826 #endif /* SKYTRAQ_ENABLE */
1827 #ifdef SUPERSTAR2_ENABLE
1828     &driver_superstar2,
1829 #endif /* SUPERSTAR2_ENABLE */
1830 #ifdef TSIP_ENABLE
1831     &driver_tsip,
1832 #endif /* TSIP_ENABLE */
1833 #ifdef ISYNC_ENABLE
1834     &driver_isync,
1835 #endif /* ISYNC_ENABLE */
1836 #ifdef UBLOX_ENABLE
1837     &driver_ubx,
1838 #endif /* UBLOX_ENABLE */
1839 #ifdef ZODIAC_ENABLE
1840     &driver_zodiac,
1841 #endif /* ZODIAC_ENABLE */
1842 
1843 #ifdef NMEA2000_ENABLE
1844     &driver_nmea2000,
1845 #endif /* NMEA2000_ENABLE */
1846 
1847 #ifdef RTCM104V2_ENABLE
1848     &driver_rtcm104v2,
1849 #endif /* RTCM104V2_ENABLE */
1850 #ifdef RTCM104V3_ENABLE
1851     &driver_rtcm104v3,
1852 #endif /* RTCM104V3_ENABLE */
1853 #ifdef GARMINTXT_ENABLE
1854     &driver_garmintxt,
1855 #endif /* GARMINTXT_ENABLE */
1856 
1857 #ifdef PASSTHROUGH_ENABLE
1858     &driver_json_passthrough,
1859 #endif /* PASSTHROUGH_ENABLE */
1860     &driver_pps,
1861     NULL,
1862 };
1863 
1864 const struct gps_type_t **gpsd_drivers = &gpsd_driver_array[0];
1865