# `serial.c`

Functions:- | This provides serial port handling services to the daemon. It handles the tricky task of scanning for and changing port parameters, especially baudrate.
--- | ---
Notes based on code as of Tue Apr 6 10:17:55 2010 -0400.
`void gpsd_tty_init(struct gps_device_t *session)` | To be called on allocating a device. Mark GPS fd closed and its baud rate unknown. If we are supporting `ntpd` shared memory segments, ensure they are initially unused.
`void cfmakeraw(struct termios *termios_p)` | Workaround for Cygwin, which is missing `cfmakeraw()`. It is pasted from man page and added in `serial.c` arbitrarily.
`speed_t gpsd_get_speed(struct termios* ttyctl)` | Calls `cfgetospeed()` and returns the baud rate, if known. Default otherwise is 115200.
`bool gpsd_set_raw(struct gps_device_t *session)` | Tries to set port to raw mode and returns success or not.

`void gpsd_set_speed(struct gps_device_t *session, speed_t speed, unsigned char parity, unsigned int stopbits)`

Sets the speed, parity and stopbits.

Lots of black magic fiddling goes on to ensure the port is flushed on the baud rate change and wakeup strings are fired off just in case the device needs prodding into life.

READ THE CODE AND COMMENTS!!!

Prior to exit, a call is made to `packet_reset()` to ensure the packet state machine is initialised.

`int gpsd_open(struct gps_device_t *session)`

Test the device and flag it as R/W if it is a character device, or R/O if it isn't.

Try to open it in non-blocking and no-control mode.

If that fails, try again, adding read-only mode. If that also fails, exit with an error.

On no error, force the saved baudrate if we have a fixed port speed (typically embedded devices). Check if we have a saved baudrate and if so, activate it.

Preset the packet type to BAD_PACKET.

Check if the device we have opened is a tty. If it is a tty, read the original terminal parameters.

Exit with an error code -1 on failure to do so.

Save the old parameters, set important control flags, then set the speed.

Finally, return the allocated fd.

`bool gpsd_write(struct gps_device_t *session, void const *buf, size_t len)` | If the device is read-only, simply return 0. If not, try to write `len` characters to the device. Waiting until all data has been sent. Return the number of bytes written.
`bool gpsd_next_hunt_setting(struct gps_device_t *session)` | Check if we have had SNIFF_RETRIES attempts at current baudrate. If not, return true. If we have exceeded the limit, reset the counter and see if there are any more rates to try at. If no (fixed baudrate or all attempts exhausted), return false, otherwise, set the next speed and return true.
`void gpsd_assert_sync(struct gps_device_t *session)` | To be called when we want to register that we've synced with a device. We've achieved first sync with the device. Remember the baudrate so we can try it first next time this device is opened.
`void gpsd_close(struct gps_device_t *session)` | If there is an active fd, check if it is a tty device. If it is, force the baudrate to 0 (should terminate the connection and de-assert control lines). Set the HUPCL flag in the original data, write the old data to the port, close the fd and clear that fd number from the session data.