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 <ctype.h> /* for isdigit() */
9 #include <dirent.h> /* for DIR */
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/param.h> /* defines BSD */
17 #include <sys/socket.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #ifdef HAVE_SYS_SYSMACROS_H
23 #include <sys/sysmacros.h> /* defines major() */
24 #endif /* HAVE_SYS_SYSMACROS_H */
25
26 #ifdef ENABLE_BLUEZ
27 #include <bluetooth/bluetooth.h>
28 #include <bluetooth/hci.h>
29 #include <bluetooth/hci_lib.h>
30 #include <bluetooth/rfcomm.h>
31 #endif /* ENABLE_BLUEZ */
32
33 #include "gpsd.h"
34
35 /* Workaround for HP-UX 11.23, which is missing CRTSCTS */
36 #ifndef CRTSCTS
37 # ifdef CNEW_RTSCTS
38 # define CRTSCTS CNEW_RTSCTS
39 # else
40 # define CRTSCTS 0
41 # endif /* CNEW_RTSCTS */
42 #endif /* !CRTSCTS */
43
gpsd_classify(const char * path)44 static sourcetype_t gpsd_classify(const char *path)
45 /* figure out what kind of device we're looking at */
46 {
47 struct stat sb;
48
49 if (stat(path, &sb) == -1)
50 return source_unknown;
51 else if (S_ISREG(sb.st_mode))
52 return source_blockdev;
53 /* this assumes we won't get UDP from a filesystem socket */
54 else if (S_ISSOCK(sb.st_mode))
55 return source_tcp;
56 /* OS-independent check for ptys using Unix98 naming convention */
57 else if (strncmp(path, "/dev/pts/", 9) == 0)
58 return source_pty;
59 else if (strncmp(path, "/dev/pps", 8) == 0)
60 return source_pps;
61 else if (S_ISFIFO(sb.st_mode))
62 return source_pipe;
63 else if (S_ISCHR(sb.st_mode)) {
64 sourcetype_t devtype = source_rs232;
65 #ifdef __linux__
66 /* Linux major device numbers live here
67 *
68 * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/devices.txt
69 *
70 * Note: This code works because Linux major device numbers are
71 * stable and architecture-independent. It is *not* a good model
72 * for other Unixes where either or both assumptions may break.
73 */
74 int devmajor = major(sb.st_rdev);
75 /* 207 are Freescale i.MX UARTs (ttymxc*) */
76 if (devmajor == 4 || devmajor == 204 || devmajor == 207)
77 devtype = source_rs232;
78 else if (devmajor == 188 || devmajor == 166)
79 devtype = source_usb;
80 else if (devmajor == 216 || devmajor == 217)
81 devtype = source_bluetooth;
82 else if (devmajor == 3 || (devmajor >= 136 && devmajor <= 143))
83 devtype = source_pty;
84 #endif /* __linux__ */
85 /*
86 * See http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
87 * for discussion how this works. Key graphs:
88 *
89 * Compilers for the old BSD base for these distributions
90 * defined the __bsdi__ macro, but none of these distributions
91 * define it now. This leaves no generic "BSD" macro defined
92 * by the compiler itself, but all UNIX-style OSes provide a
93 * <sys/param.h> file. On BSD distributions, and only on BSD
94 * distributions, this file defines a BSD macro that's set to
95 * the OS version. Checking for this generic macro is more
96 * robust than looking for known BSD distributions with
97 * __DragonFly__, __FreeBSD__, __NetBSD__, and __OpenBSD__
98 * macros.
99 *
100 * Apple's OSX for the Mac and iOS for iPhones and iPads are
101 * based in part on a fork of FreeBSD distributed as
102 * Darwin. As such, OSX and iOS also define the BSD macro
103 * within <sys/param.h>. However, compilers for OSX, iOS, and
104 * Darwin do not define __unix__. To detect all BSD OSes,
105 * including OSX, iOS, and Darwin, use an #if/#endif that
106 * checks for __unix__ along with __APPLE__ and __MACH__ (see
107 * the later section on OSX and iOS).
108 */
109 #ifdef BSD
110 /*
111 * Hacky check for pty, which is what really matters for avoiding
112 * adaptive delay.
113 */
114 if (strncmp(path, "/dev/ttyp", 9) == 0 ||
115 strncmp(path, "/dev/ttyq", 9) == 0)
116 devtype = source_pty;
117 else if (strncmp(path, "/dev/ttyU", 9) == 0 ||
118 strncmp(path, "/dev/dtyU", 9) == 0)
119 devtype = source_usb;
120 /* XXX bluetooth */
121 #endif /* BSD */
122 return devtype;
123 } else
124 return source_unknown;
125 }
126
127 #ifdef __linux__
128
fusercount(const char * path)129 static int fusercount(const char *path)
130 /* return true if any process has the specified path open */
131 {
132 DIR *procd, *fdd;
133 struct dirent *procentry, *fdentry;
134 char procpath[64], fdpath[64], linkpath[64];
135 int cnt = 0;
136
137 if ((procd = opendir("/proc")) == NULL)
138 return -1;
139 while ((procentry = readdir(procd)) != NULL) {
140 if (isdigit(procentry->d_name[0])==0)
141 continue;
142 /* longest procentry->d_name I could find was 12 */
143 (void)snprintf(procpath, sizeof(procpath),
144 "/proc/%.20s/fd/", procentry->d_name);
145 if ((fdd = opendir(procpath)) == NULL)
146 continue;
147 while ((fdentry = readdir(fdd)) != NULL) {
148 (void)strlcpy(fdpath, procpath, sizeof(fdpath));
149 (void)strlcat(fdpath, fdentry->d_name, sizeof(fdpath));
150 (void)memset(linkpath, '\0', sizeof(linkpath));
151 if (readlink(fdpath, linkpath, sizeof(linkpath)) == -1)
152 continue;
153 if (strcmp(linkpath, path) == 0) {
154 ++cnt;
155 }
156 }
157 (void)closedir(fdd);
158 }
159 (void)closedir(procd);
160
161 return cnt;
162 }
163 #endif /* __linux__ */
164
gpsd_tty_init(struct gps_device_t * session)165 void gpsd_tty_init(struct gps_device_t *session)
166 /* to be called on allocating a device */
167 {
168 /* mark GPS fd closed and its baud rate unknown */
169 session->gpsdata.gps_fd = -1;
170 session->saved_baud = -1;
171 session->zerokill = false;
172 session->reawake = (time_t)0;
173 }
174
175 #if !defined(HAVE_CFMAKERAW)
176 /*
177 * Local implementation of cfmakeraw (which is not specified by
178 * POSIX; see matching declaration in gpsd.h).
179 */
180 /* Pasted from man page; added in serial.c arbitrarily */
cfmakeraw(struct termios * termios_p)181 void cfmakeraw(struct termios *termios_p)
182 {
183 termios_p->c_iflag &=
184 ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
185 termios_p->c_oflag &= ~OPOST;
186 termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
187 termios_p->c_cflag &= ~(CSIZE | PARENB);
188 termios_p->c_cflag |= CS8;
189 }
190 #endif /* !defined(HAVE_CFMAKERAW) */
191
gpsd_get_speed_termios(const struct termios * ttyctl)192 static speed_t gpsd_get_speed_termios(const struct termios *ttyctl)
193 {
194 speed_t code = cfgetospeed(ttyctl);
195 switch (code) {
196 case B300:
197 return (300);
198 case B1200:
199 return (1200);
200 case B2400:
201 return (2400);
202 case B4800:
203 return (4800);
204 case B9600:
205 return (9600);
206 case B19200:
207 return (19200);
208 case B38400:
209 return (38400);
210 case B57600:
211 return (57600);
212 case B115200:
213 return (115200);
214 case B230400:
215 return (230400);
216 default: /* B0 */
217 return 0;
218 }
219 }
220
gpsd_get_speed(const struct gps_device_t * dev)221 speed_t gpsd_get_speed(const struct gps_device_t *dev)
222 {
223 return gpsd_get_speed_termios(&dev->ttyset);
224 }
225
gpsd_get_speed_old(const struct gps_device_t * dev)226 speed_t gpsd_get_speed_old(const struct gps_device_t *dev)
227 {
228 return gpsd_get_speed_termios(&dev->ttyset_old);
229 }
230
gpsd_get_parity(const struct gps_device_t * dev)231 char gpsd_get_parity(const struct gps_device_t *dev)
232 {
233 char parity = 'N';
234 if ((dev->ttyset.c_cflag & (PARENB | PARODD)) == (PARENB | PARODD))
235 parity = 'O';
236 else if ((dev->ttyset.c_cflag & PARENB) == PARENB)
237 parity = 'E';
238 return parity;
239 }
240
gpsd_get_stopbits(const struct gps_device_t * dev)241 int gpsd_get_stopbits(const struct gps_device_t *dev)
242 {
243 int stopbits = 0;
244 if ((dev->ttyset.c_cflag & CS8) == CS8)
245 stopbits = 1;
246 else if ((dev->ttyset.c_cflag & (CS7 | CSTOPB)) == (CS7 | CSTOPB))
247 stopbits = 2;
248 return stopbits;
249 }
250
gpsd_set_raw(struct gps_device_t * session)251 bool gpsd_set_raw(struct gps_device_t * session)
252 {
253 (void)cfmakeraw(&session->ttyset);
254 if (-1 == tcsetattr(session->gpsdata.gps_fd, TCIOFLUSH, &session->ttyset)) {
255 GPSD_LOG(LOG_ERROR, &session->context->errout,
256 "SER: error changing port attributes: %s\n", strerror(errno));
257 return false;
258 }
259
260 return true;
261 }
262
gpsd_set_speed(struct gps_device_t * session,speed_t speed,char parity,unsigned int stopbits)263 void gpsd_set_speed(struct gps_device_t *session,
264 speed_t speed, char parity, unsigned int stopbits)
265 {
266 speed_t rate;
267 struct timespec delay;
268
269 if (0 < session->context->fixed_port_speed) {
270 speed = session->context->fixed_port_speed;
271 }
272 if ('\0' != session->context->fixed_port_framing[0]) {
273 // ignore length, stopbits=2 forces length 7.
274 parity = session->context->fixed_port_framing[1];
275 stopbits = session->context->fixed_port_framing[2] - '0';
276 }
277
278 /*
279 * Yes, you can set speeds that aren't in the hunt loop. If you
280 * do this, and you aren't on Linux where baud rate is preserved
281 * across port closings, you've screwed yourself. Don't do that!
282 */
283 if (speed < 300)
284 rate = B0;
285 else if (speed < 1200)
286 rate = B300;
287 else if (speed < 2400)
288 rate = B1200;
289 else if (speed < 4800)
290 rate = B2400;
291 else if (speed < 9600)
292 rate = B4800;
293 else if (speed < 19200)
294 rate = B9600;
295 else if (speed < 38400)
296 rate = B19200;
297 else if (speed < 57600)
298 rate = B38400;
299 else if (speed < 115200)
300 rate = B57600;
301 else if (speed < 230400)
302 rate = B115200;
303 else
304 rate = B230400;
305
306 /* backward-compatibility hack */
307 switch (parity) {
308 case 'E':
309 // FALLTHROUGH
310 case (char)2:
311 parity = 'E';
312 break;
313 case 'O':
314 // FALLTHROUGH
315 case (char)1:
316 parity = 'O';
317 break;
318 case 'N':
319 // FALLTHROUGH
320 case (char)0:
321 // FALLTHROUGH
322 default:
323 parity = 'N'; /* without this we might emit malformed JSON */
324 break;
325 }
326
327 if (rate != cfgetispeed(&session->ttyset)
328 || parity != session->gpsdata.dev.parity
329 || stopbits != session->gpsdata.dev.stopbits) {
330
331 /*
332 * Don't mess with this conditional! Speed zero is supposed to mean
333 * to leave the port speed at whatever it currently is. This leads
334 * to excellent behavior on Linux, which preserves baudrate across
335 * serial device closes - it means that if you've opened this
336 * device before you typically don't have to hunt at all because
337 * it's still at the same speed you left it - you'll typically
338 * get packet lock within 1.5 seconds. Alas, the BSDs and OS X
339 * aren't so nice.
340 */
341 if (rate != B0) {
342 (void)cfsetispeed(&session->ttyset, rate);
343 (void)cfsetospeed(&session->ttyset, rate);
344 }
345 session->ttyset.c_iflag &= ~(PARMRK | INPCK);
346 session->ttyset.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
347 session->ttyset.c_cflag |= (stopbits == 2 ? CS7 | CSTOPB : CS8);
348 switch (parity) {
349 case 'E':
350 session->ttyset.c_iflag |= INPCK;
351 session->ttyset.c_cflag |= PARENB;
352 break;
353 case 'O':
354 session->ttyset.c_iflag |= INPCK;
355 session->ttyset.c_cflag |= PARENB | PARODD;
356 break;
357 }
358 if (0 != tcsetattr(session->gpsdata.gps_fd, TCSANOW,
359 &session->ttyset)) {
360 /* strangely this fails on non-serial ports, but if
361 * we do not try, we get other failures.
362 * so ignore for now, as we always have, until it can
363 * be nailed down.
364 *
365 * GPSD_LOG(&session->context->errout, LOG_ERROR,
366 * "SER: error setting port attributes: %s, sourcetype: %d\n",
367 * strerror(errno), session->sourcetype);
368 * return;
369 */
370 }
371
372 /*
373 * Serious black magic begins here. Getting this code wrong can cause
374 * failures to lock to a correct speed, and not clean reproducible
375 * failures but flukey hardware- and timing-dependent ones. So
376 * be very sure you know what you're doing before hacking it, and
377 * test thoroughly.
378 *
379 * The fundamental problem here is that serial devices take time
380 * to settle into a new baud rate after tcsetattr() is issued. Until
381 * they do so, input will be arbitarily garbled. Normally this
382 * is not a big problem, but in our hunt loop the garbling can trash
383 * a long enough prefix of each sample to prevent detection of a
384 * packet header. We could address the symptom by making the sample
385 * size enough larger that subtracting the maximum length of garble
386 * would still leave a sample longer than the maximum packet size.
387 * But it's better (and more efficient) to address the disease.
388 *
389 * In theory, one might think that not even a tcflush() call would
390 * be needed, with tcsetattr() delaying its return until the device
391 * is in a good state. For simple devices like a 14550 UART that
392 * have fixed response timings this may even work, if the driver
393 * writer was smart enough to delay the return by the right number
394 * of milliseconds after poking the device port(s).
395 *
396 * Problems may arise if the driver's timings are off. Or we may
397 * be talking to a USB device like the pl2303 commonly used in GPS
398 * mice; on these, the change will not happen immediately because
399 * it has to be sent as a message to the external processor that
400 * has to act upon it, and that processor may still have buffered
401 * data in its own FIFO. In this case the expected delay may be
402 * too large and too variable (depending on the details of how the
403 * USB device is integrated with its symbiont hardware) to be put
404 * in the driver.
405 *
406 * So, somehow, we have to introduce a delay after tcsatattr()
407 * returns sufficient to allow *any* device to settle. On the other
408 * hand, a really long delay will make gpsd device registration
409 * unpleasantly laggy.
410 *
411 * The classic way to address this is with a tcflush(), counting
412 * on it to clear the device FIFO. But that call may clear only the
413 * kernel buffers, not the device's hardware FIFO, so it may not
414 * be sufficient by itself.
415 *
416 * flush followed by a 200-millisecond delay followed by flush has
417 * been found to work reliably on the pl2303. It is also known
418 * from testing that a 100-millisec delay is too short, allowing
419 * occasional failure to lock.
420 */
421 (void)tcflush(session->gpsdata.gps_fd, TCIOFLUSH);
422
423 /* wait 200,000 uSec */
424 delay.tv_sec = 0;
425 delay.tv_nsec = 200000000L;
426 nanosleep(&delay, NULL);
427 (void)tcflush(session->gpsdata.gps_fd, TCIOFLUSH);
428 }
429 GPSD_LOG(LOG_INF, &session->context->errout,
430 "SER: speed %lu, %d%c%d\n",
431 (unsigned long)gpsd_get_speed(session), 9 - stopbits, parity,
432 stopbits);
433
434 session->gpsdata.dev.baudrate = (unsigned int)speed;
435 session->gpsdata.dev.parity = parity;
436 session->gpsdata.dev.stopbits = stopbits;
437
438 /*
439 * The device might need a wakeup string before it will send data.
440 * If we don't know the device type, ship it every driver's wakeup
441 * in hopes it will respond. But not to USB or Bluetooth, because
442 * shipping probe strings to unknown USB serial adaptors or
443 * Bluetooth devices may spam devices that aren't GPSes at all and
444 * could become confused.
445 */
446 if (!session->context->readonly
447 && session->sourcetype != source_usb
448 && session->sourcetype != source_bluetooth) {
449 if (isatty(session->gpsdata.gps_fd) != 0
450 && !session->context->readonly) {
451 if (session->device_type == NULL) {
452 const struct gps_type_t **dp;
453 for (dp = gpsd_drivers; *dp; dp++)
454 if ((*dp)->event_hook != NULL)
455 (*dp)->event_hook(session, event_wakeup);
456 } else if (session->device_type->event_hook != NULL)
457 session->device_type->event_hook(session, event_wakeup);
458 }
459 }
460 packet_reset(&session->lexer);
461 }
462
gpsd_serial_open(struct gps_device_t * session)463 int gpsd_serial_open(struct gps_device_t *session)
464 /* open a device for access to its data
465 * return: the opened file descriptor
466 * PLACEHOLDING_FD - for /dev/ppsX
467 * UNALLOCATED_FD - for open failure
468 */
469
470 {
471 mode_t mode = (mode_t) O_RDWR;
472
473 session->sourcetype = gpsd_classify(session->gpsdata.dev.path);
474 session->servicetype = service_sensor;
475
476 /* we may need to hold on to this slot without opening the device */
477 if (source_pps == session->sourcetype) {
478 (void)gpsd_switch_driver(session, "PPS");
479 return PLACEHOLDING_FD;
480 }
481
482 if (session->context->readonly
483 || (session->sourcetype <= source_blockdev)) {
484 mode = (mode_t) O_RDONLY;
485 GPSD_LOG(LOG_INF, &session->context->errout,
486 "SER: opening read-only GPS data source type %d and at '%s'\n",
487 (int)session->sourcetype, session->gpsdata.dev.path);
488 } else {
489 GPSD_LOG(LOG_INF, &session->context->errout,
490 "SER: opening GPS data source type %d at '%s'\n",
491 (int)session->sourcetype, session->gpsdata.dev.path);
492 }
493 #ifdef ENABLE_BLUEZ
494 if (bachk(session->gpsdata.dev.path) == 0) {
495 struct sockaddr_rc addr = { 0, *BDADDR_ANY, 0};
496 session->gpsdata.gps_fd = socket(AF_BLUETOOTH,
497 SOCK_STREAM,
498 BTPROTO_RFCOMM);
499 addr.rc_family = AF_BLUETOOTH;
500 addr.rc_channel = (uint8_t) 1;
501 (void) str2ba(session->gpsdata.dev.path, &addr.rc_bdaddr);
502 if (connect(session->gpsdata.gps_fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
503 if (errno != EINPROGRESS && errno != EAGAIN) {
504 (void)close(session->gpsdata.gps_fd);
505 GPSD_LOG(LOG_ERROR, &session->context->errout,
506 "SER: bluetooth socket connect failed: %s\n",
507 strerror(errno));
508 return UNALLOCATED_FD;
509 }
510 GPSD_LOG(LOG_ERROR, &session->context->errout,
511 "SER: bluetooth socket connect in progress or again : %s\n",
512 strerror(errno));
513 }
514 (void)fcntl(session->gpsdata.gps_fd, F_SETFL, (int)mode);
515 GPSD_LOG(LOG_PROG, &session->context->errout,
516 "SER: bluez device open success: %s %s\n",
517 session->gpsdata.dev.path, strerror(errno));
518 } else
519 #endif /* BLUEZ */
520 {
521 /*
522 * We open with O_NONBLOCK because we want to not get hung if
523 * the CLOCAL flag is off. Need to keep O_NONBLOCK so the main
524 * loop does not clock on an unresponsive read() from a receiver.
525 */
526 errno = 0;
527 if ((session->gpsdata.gps_fd =
528 open(session->gpsdata.dev.path,
529 (int)(mode | O_NONBLOCK | O_NOCTTY))) == -1) {
530 GPSD_LOG(LOG_ERROR, &session->context->errout,
531 "SER: device open of %s failed: %s - "
532 "retrying read-only\n",
533 session->gpsdata.dev.path,
534 strerror(errno));
535 if ((session->gpsdata.gps_fd =
536 open(session->gpsdata.dev.path,
537 O_RDONLY | O_NONBLOCK | O_NOCTTY)) == -1) {
538 GPSD_LOG(LOG_ERROR, &session->context->errout,
539 "SER: read-only device open of %s failed: %s\n",
540 session->gpsdata.dev.path,
541 strerror(errno));
542 return UNALLOCATED_FD;
543 }
544
545 GPSD_LOG(LOG_PROG, &session->context->errout,
546 "SER: file device open of %s succeeded\n",
547 session->gpsdata.dev.path);
548 }
549 }
550
551 /*
552 * Ideally we want to exclusion-lock the device before doing any reads.
553 * It would have been best to do this at open(2) time, but O_EXCL
554 * doesn't work without O_CREAT.
555 *
556 * We have to make an exception for ptys, which are intentionally
557 * opened by another process on the master side, otherwise we'll
558 * break all our regression tests.
559 *
560 * We also exclude bluetooth device because the bluetooth daemon opens them.
561 */
562 if (!(session->sourcetype == source_pty ||
563 session->sourcetype == source_bluetooth)) {
564 #ifdef TIOCEXCL
565 /*
566 * Try to block other processes from using this device while we
567 * have it open (later opens should return EBUSY). Won't work
568 * against anything with root privileges, alas.
569 */
570 (void)ioctl(session->gpsdata.gps_fd, (unsigned long)TIOCEXCL);
571 #endif /* TIOCEXCL */
572
573 #ifdef __linux__
574 /*
575 * Don't touch devices already opened by another process.
576 */
577 if (fusercount(session->gpsdata.dev.path) > 1) {
578 GPSD_LOG(LOG_ERROR, &session->context->errout,
579 "SER: %s already opened by another process\n",
580 session->gpsdata.dev.path);
581 (void)close(session->gpsdata.gps_fd);
582 session->gpsdata.gps_fd = UNALLOCATED_FD;
583 return UNALLOCATED_FD;
584 }
585 #endif /* __linux__ */
586 }
587
588 if (0 < session->context->fixed_port_speed) {
589 session->saved_baud = session->context->fixed_port_speed;
590 }
591
592 if (session->saved_baud != -1) {
593 (void)cfsetispeed(&session->ttyset, (speed_t)session->saved_baud);
594 (void)cfsetospeed(&session->ttyset, (speed_t)session->saved_baud);
595 if (0 != tcsetattr(session->gpsdata.gps_fd, TCSANOW,
596 &session->ttyset)) {
597 GPSD_LOG(LOG_ERROR, &session->context->errout,
598 "SER: Error setting port attributes: %s\n",
599 strerror(errno));
600 }
601 (void)tcflush(session->gpsdata.gps_fd, TCIOFLUSH);
602 }
603
604 session->lexer.type = BAD_PACKET;
605 if ( 0 != isatty(session->gpsdata.gps_fd) ) {
606 speed_t new_speed;
607 char new_parity; // E, N, O
608 unsigned int new_stop;
609
610 /* Save original terminal parameters */
611 if (tcgetattr(session->gpsdata.gps_fd, &session->ttyset_old) != 0)
612 return UNALLOCATED_FD;
613 session->ttyset = session->ttyset_old;
614 /* twiddle the speed, parity, etc. but only on real serial ports */
615 memset(session->ttyset.c_cc, 0, sizeof(session->ttyset.c_cc));
616 //session->ttyset.c_cc[VTIME] = 1;
617 /*
618 * Tip from Chris Kuethe: the FIDI chip used in the Trip-Nav
619 * 200 (and possibly other USB GPSes) gets completely hosed
620 * in the presence of flow control. Thus, turn off CRTSCTS.
621 *
622 * This is not ideal. Setting no parity here will mean extra
623 * initialization time for some devices, like certain Trimble
624 * boards, that want 7O2 or other non-8N1 settings. But starting
625 * the hunt loop at 8N1 will minimize the average sync time
626 * over all devices.
627 */
628 session->ttyset.c_cflag &= ~(PARENB | PARODD | CRTSCTS | CSTOPB);
629 session->ttyset.c_cflag |= CREAD | CLOCAL;
630 session->ttyset.c_iflag = session->ttyset.c_oflag =
631 session->ttyset.c_lflag = (tcflag_t) 0;
632
633 session->baudindex = 0;
634 if (0 < session->context->fixed_port_speed) {
635 new_speed = session->context->fixed_port_speed;
636 } else {
637 new_speed = gpsd_get_speed_old(session);
638 }
639 if ('\0' == session->context->fixed_port_framing[0]) {
640 new_parity = 'N';
641 new_stop = 1;
642 } else {
643 // ignore length, stopbits=2 forces length 7.
644 new_parity = session->context->fixed_port_framing[1];
645 new_stop = session->context->fixed_port_framing[2] - '0';
646 }
647 gpsd_set_speed(session, new_speed, new_parity, new_stop);
648 }
649
650 /* Used to turn off O_NONBLOCK here, but best not to block trying
651 * to read from an unresponsive receiver. */
652
653 /* required so parity field won't be '\0' if saved speed matches */
654 if (session->sourcetype <= source_blockdev) {
655 session->gpsdata.dev.parity = 'N';
656 session->gpsdata.dev.stopbits = 1;
657 }
658
659 GPSD_LOG(LOG_SPIN, &session->context->errout,
660 "SER: open(%s) -> %d in gpsd_serial_open()\n",
661 session->gpsdata.dev.path, session->gpsdata.gps_fd);
662 return session->gpsdata.gps_fd;
663 }
664
gpsd_serial_write(struct gps_device_t * session,const char * buf,const size_t len)665 ssize_t gpsd_serial_write(struct gps_device_t * session,
666 const char *buf, const size_t len)
667 {
668 ssize_t status;
669 bool ok;
670 if (session == NULL ||
671 session->context == NULL || session->context->readonly)
672 return 0;
673 status = write(session->gpsdata.gps_fd, buf, len);
674 ok = (status == (ssize_t) len);
675 (void)tcdrain(session->gpsdata.gps_fd);
676 /* extra guard prevents expensive hexdump calls */
677 if (session->context->errout.debug >= LOG_IO) {
678 char scratchbuf[MAX_PACKET_LENGTH*2+1];
679 GPSD_LOG(LOG_IO, &session->context->errout,
680 "SER: => GPS: %s%s\n",
681 gpsd_packetdump(scratchbuf, sizeof(scratchbuf),
682 (char *)buf, len), ok ? "" : " FAILED");
683 }
684 return status;
685 }
686
687 /*
688 * This constant controls how long the packet sniffer will spend looking
689 * for a packet leader before it gives up. It *must* be larger than
690 * MAX_PACKET_LENGTH or we risk never syncing up at all. Large values
691 * will produce annoying startup lag.
692 */
693 #define SNIFF_RETRIES (MAX_PACKET_LENGTH + 128)
694
695 /* advance to the next hunt setting */
gpsd_next_hunt_setting(struct gps_device_t * session)696 bool gpsd_next_hunt_setting(struct gps_device_t * session)
697 {
698 /* every rate we're likely to see on an old GPS */
699 // FIXME add new rates
700 static unsigned int rates[] =
701 {0, 4800, 9600, 19200, 38400, 57600, 115200, 230400};
702
703 char new_parity; // E, N, O
704 unsigned int new_stop;
705
706 /* don't waste time in the hunt loop if this is not actually a tty */
707 if (0 == isatty(session->gpsdata.gps_fd))
708 return false;
709
710 /* ...or if it's nominally a tty but delivers only PPS and no data */
711 if (session->sourcetype == source_pps)
712 return false;
713
714 if (session->lexer.retry_counter++ >= SNIFF_RETRIES) {
715 if (0 < session->context->fixed_port_speed) {
716 // fixed speed, don't hunt
717 // this prevents framing hunt?
718 return false;
719 }
720
721 if (session->baudindex++ >=
722 (unsigned int)(sizeof(rates) / sizeof(rates[0])) - 1) {
723
724 session->baudindex = 0;
725 if ('\0' != session->context->fixed_port_framing[0]) {
726 return false; /* hunt is over, no sync */
727 }
728
729 // More stop bits to try?
730 if (session->gpsdata.dev.stopbits++ >= 2) {
731 return false; /* hunt is over, no sync */
732 }
733 }
734
735 if ('\0' == session->context->fixed_port_framing[0]) {
736 new_parity = session->gpsdata.dev.parity;
737 new_stop = session->gpsdata.dev.stopbits;
738 } else {
739 // ignore length, stopbits=2 forces length 7.
740 new_parity = session->context->fixed_port_framing[1];
741 new_stop = session->context->fixed_port_framing[2] - '0';
742 }
743
744 gpsd_set_speed(session, rates[session->baudindex], new_parity,
745 new_stop);
746 session->lexer.retry_counter = 0;
747 }
748 return true; /* keep hunting */
749 }
750
gpsd_assert_sync(struct gps_device_t * session)751 void gpsd_assert_sync(struct gps_device_t *session)
752 /* to be called when we want to register that we've synced with a device */
753 {
754 /*
755 * We've achieved first sync with the device. Remember the
756 * baudrate so we can try it first next time this device
757 * is opened.
758 */
759 if (session->saved_baud == -1)
760 session->saved_baud = (int)cfgetispeed(&session->ttyset);
761 }
762
gpsd_close(struct gps_device_t * session)763 void gpsd_close(struct gps_device_t *session)
764 {
765 if (!BAD_SOCKET(session->gpsdata.gps_fd)) {
766 #ifdef TIOCNXCL
767 (void)ioctl(session->gpsdata.gps_fd, (unsigned long)TIOCNXCL);
768 #endif /* TIOCNXCL */
769 if (!session->context->readonly)
770 (void)tcdrain(session->gpsdata.gps_fd);
771 if (isatty(session->gpsdata.gps_fd) != 0) {
772 /* force hangup on close on systems that don't do HUPCL properly */
773 (void)cfsetispeed(&session->ttyset, (speed_t) B0);
774 (void)cfsetospeed(&session->ttyset, (speed_t) B0);
775 (void)tcsetattr(session->gpsdata.gps_fd, TCSANOW,
776 &session->ttyset);
777 }
778 /* this is the clean way to do it */
779 session->ttyset_old.c_cflag |= HUPCL;
780 /*
781 * Don't revert the serial parameters if we didn't have to mess with
782 * them the first time. Economical, and avoids tripping over an
783 * obscure Linux 2.6 kernel bug that disables threaded
784 * ioctl(TIOCMWAIT) on a device after tcsetattr() is called.
785 */
786 if ((cfgetispeed(&session->ttyset_old) !=
787 cfgetispeed(&session->ttyset)) ||
788 ((session->ttyset_old.c_cflag & CSTOPB) !=
789 (session->ttyset.c_cflag & CSTOPB))) {
790 /*
791 * If we revert, keep the most recent baud rate.
792 * Cuts down on autobaud overhead the next time.
793 */
794 (void)cfsetispeed(&session->ttyset_old,
795 (speed_t) session->gpsdata.dev.baudrate);
796 (void)cfsetospeed(&session->ttyset_old,
797 (speed_t) session->gpsdata.dev.baudrate);
798 (void)tcsetattr(session->gpsdata.gps_fd, TCSANOW,
799 &session->ttyset_old);
800 }
801 GPSD_LOG(LOG_SPIN, &session->context->errout,
802 "SER: close(%d) in gpsd_close(%s)\n",
803 session->gpsdata.gps_fd, session->gpsdata.dev.path);
804 (void)close(session->gpsdata.gps_fd);
805 session->gpsdata.gps_fd = -1;
806 }
807 }
808