+void serial_restore_params(int fd, void *backup)
+{
+#ifdef _WIN32
+ /* TODO */
+#else
+ tcsetattr(fd, TCSADRAIN, (struct termios *)backup);
+#endif
+}
+
+/*
+ * flowcontrol 1 = rts/cts 2 = xon/xoff
+ * parity 0 = none, 1 = even, 2 = odd
+ */
+int serial_set_params(int fd, int speed, int bits, int parity, int stopbits,
+ int flowcontrol)
+{
+#ifdef _WIN32
+ DCB dcb;
+
+ if (!GetCommState(hdl, &dcb)) {
+ /* TODO: Error handling. */
+ }
+
+ /* TODO: Rename 'speed' to 'baudrate'. */
+ switch(speed) {
+ /* TODO: Support for higher baud rates. */
+ case 115200:
+ dcb.BaudRate = CBR_115200;
+ break;
+ case 57600:
+ dcb.BaudRate = CBR_57600;
+ break;
+ case 38400:
+ dcb.BaudRate = CBR_38400;
+ break;
+ case 19200:
+ dcb.BaudRate = CBR_19200;
+ break;
+ case 9600:
+ dcb.BaudRate = CBR_9600;
+ break;
+ default:
+ /* TODO: Error handling. */
+ break;
+ }
+ dcb.ByteSize = bits;
+ dcb.Parity = NOPARITY; /* TODO: Don't hardcode. */
+ dcb.StopBits = ONESTOPBIT; /* TODO: Don't hardcode. */
+
+ if (!SetCommState(hdl, &dcb)) {
+ /* TODO: Error handling. */
+ }
+#else
+ struct termios term;
+ speed_t baud;
+
+ switch (speed) {
+ case 9600:
+ baud = B9600;
+ break;
+ case 38400:
+ baud = B38400;
+ break;
+ case 57600:
+ baud = B57600;
+ break;
+ case 115200:
+ baud = B115200;
+ break;
+ case 460800:
+ baud = B460800;
+ break;
+ default:
+ return SIGROK_ERR;
+ }
+
+ if (tcgetattr(fd, &term) < 0)
+ return SIGROK_ERR;
+ if (cfsetispeed(&term, baud) < 0)
+ return SIGROK_ERR;
+
+ term.c_cflag &= ~CSIZE;
+ switch (bits) {
+ case 8:
+ term.c_cflag |= CS8;
+ break;
+ case 7:
+ term.c_cflag |= CS7;
+ break;
+ default:
+ return SIGROK_ERR;
+ }
+
+ term.c_cflag &= ~CSTOPB;
+ switch (stopbits) {
+ case 1:
+ break;
+ case 2:
+ term.c_cflag |= CSTOPB;
+ default:
+ return SIGROK_ERR;
+ }
+
+ term.c_cflag &= ~(IXON | IXOFF | CRTSCTS);
+ switch (flowcontrol) {
+ case 2:
+ term.c_cflag |= IXON | IXOFF;
+ break;
+ case 1:
+ term.c_cflag |= CRTSCTS;
+ default:
+ return SIGROK_ERR;
+ }
+
+ term.c_iflag &= ~IGNPAR;
+ term.c_cflag &= ~(PARODD | PARENB);
+ switch (parity) {
+ case 0:
+ term.c_iflag |= IGNPAR;
+ break;
+ case 1:
+ term.c_cflag |= PARENB;
+ break;
+ case 2:
+ term.c_cflag |= PARENB | PARODD;
+ break;
+ default:
+ return SIGROK_ERR;
+ }
+
+ if (tcsetattr(fd, TCSADRAIN, &term) < 0)
+ return SIGROK_ERR;
+#endif
+
+ return SIGROK_OK;
+}