+static gint32
+get_signal_code (MonoSerialSignal signal)
+{
+ switch (signal) {
+ case Cd:
+ return TIOCM_CAR;
+ case Cts:
+ return TIOCM_CTS;
+ case Dsr:
+ return TIOCM_DSR;
+ case Dtr:
+ return TIOCM_DTR;
+ case Rts:
+ return TIOCM_RTS;
+ default:
+ return 0;
+ }
+
+ /* Not reached */
+ return 0;
+}
+
+static MonoSerialSignal
+get_mono_signal_codes (int signals)
+{
+ MonoSerialSignal retval = NoneSignal;
+
+ if ((signals & TIOCM_CAR) != 0)
+ retval |= Cd;
+ if ((signals & TIOCM_CTS) != 0)
+ retval |= Cts;
+ if ((signals & TIOCM_DSR) != 0)
+ retval |= Dsr;
+ if ((signals & TIOCM_DTR) != 0)
+ retval |= Dtr;
+ if ((signals & TIOCM_RTS) != 0)
+ retval |= Rts;
+
+ return retval;
+}
+
+MonoSerialSignal
+get_signals (int fd, gint32 *error)
+{
+ int signals;
+
+ *error = 0;
+
+ if (ioctl (fd, TIOCMGET, &signals) == -1) {
+ *error = -1;
+ return NoneSignal;
+ }
+
+ return get_mono_signal_codes (signals);
+}
+
+gint32
+set_signal (int fd, MonoSerialSignal signal, gboolean value)
+{
+ int signals, expected, activated;
+
+ expected = get_signal_code (signal);
+ if (ioctl (fd, TIOCMGET, &signals) == -1)
+ return -1;
+
+ activated = (signals & expected) != 0;
+ if (activated == value) /* Already set */
+ return 1;
+
+ if (value)
+ signals |= expected;
+ else
+ signals &= ~expected;
+
+ if (ioctl (fd, TIOCMSET, &signals) == -1)
+ return -1;
+
+ return 1;
+}
+
+void
+breakprop (int fd)
+{
+ tcsendbreak (fd, 0);
+}
+
+gboolean
+poll_serial (int fd, gint32 *error, int timeout)
+{
+ struct pollfd pinfo;
+
+ *error = 0;
+
+ pinfo.fd = fd;
+ pinfo.events = POLLIN;
+ pinfo.revents = 0;
+
+ while (poll (&pinfo, 1, timeout) == -1 && errno == EINTR) {
+ /* EINTR is an OK condition, we should not throw in the upper layer an IOException */
+ if (errno != EINTR){
+ *error = -1;
+ return FALSE;
+ }
+ }
+
+ return (pinfo.revents & POLLIN) != 0 ? 1 : 0;