drivers.c 71 KB

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