#include <fcntl.h>
#include <string.h>
#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <errno.h>
#include <glib.h>
+/* This is for FIONREAD on solaris */
+#if defined(sun)
+#include <sys/filio.h>
+#endif
+
+/* This is a copy of System.IO.Ports.Handshake */
+typedef enum {
+ NoneHandshake = 0,
+ XOnXOff = 1,
+ RequestToSend = 2,
+ RequestToSendXOnXOff = 3
+} MonoHandshake;
+
+/* This is a copy of System.IO.Ports.Parity */
+typedef enum {
+ NoneParity = 0,
+ Odd = 1,
+ Even = 2,
+ Mark = 3,
+ Space = 4
+} MonoParity;
+
+/* This is a copy of System.IO.Ports.StopBits */
+typedef enum {
+ NoneStopBits = 0,
+ One = 1,
+ Two = 2,
+ OnePointFive = 3
+} MonoStopBits;
+
+/* This is a copy of System.IO.Ports.SerialSignal */
+typedef enum {
+ NoneSignal,
+ Cd = 1, /* Carrier detect */
+ Cts = 2, /* Clear to send */
+ Dsr = 4, /* Data set ready */
+ Dtr = 8, /* Data terminal ready */
+ Rts = 16 /* Request to send */
+} MonoSerialSignal;
+
int
open_serial (char* devfile)
{
tcflush(fd, TCIOFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
- fcntl (fd, F_SETFL, O_NONBLOCK);
-
return fd;
}
}
guint32
-read_serial (int fd, guchar *buffer, int offset, int count, int timeout)
+read_serial (int fd, guchar *buffer, int offset, int count)
{
guint32 n;
- struct pollfd ufd;
-
- ufd.fd = fd;
- ufd.events = POLLHUP | POLLIN | POLLERR;
-
- poll (&ufd, 1, timeout);
-
- if ((ufd.revents & POLLIN) != POLLIN) {
- return -1;
- }
n = read (fd, buffer + offset, count);
ufd.fd = fd;
ufd.events = POLLHUP | POLLOUT | POLLERR;
- poll (&ufd, 1, timeout);
+ while (poll (&ufd, 1, timeout) == -1 && errno == EINTR){
+
+ }
if ((ufd.revents & POLLOUT) != POLLOUT) {
return;
tcflush(fd, input ? TCIFLUSH : TCOFLUSH);
}
+gint32
+get_bytes_in_buffer (int fd, gboolean input)
+{
+ gint32 retval;
+
+ if (ioctl (fd, input ? FIONREAD : TIOCOUTQ, &retval) == -1) {
+ return -1;
+ }
+
+ return retval;
+}
+
gboolean
-set_attributes (int fd, int baud_rate, int parity, int dataBits, int stopBits, int handshake)
+set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake)
{
struct termios newtio;
}
switch (parity) {
- case 0: /* Even */
- newtio.c_iflag &= ~IGNPAR;
- newtio.c_cflag |= PARENB;
- break;
- case 1: /* Mark */
- /* XXX unhandled */
- break;
- case 2: /* None */
+ case NoneParity: /* None */
newtio.c_iflag |= IGNPAR;
newtio.c_cflag &= ~(PARENB | PARODD);
break;
- case 3: /* Odd */
+ case Odd: /* Odd */
newtio.c_iflag &= ~IGNPAR;
newtio.c_cflag |= PARENB | PARODD;
break;
- case 4: /* Space */
+ case Even: /* Even */
+ newtio.c_iflag &= ~(IGNPAR | PARODD);
+ newtio.c_cflag |= PARENB;
+ break;
+ case Mark: /* Mark */
+ /* XXX unhandled */
+ break;
+ case Space: /* Space */
/* XXX unhandled */
break;
}
newtio.c_cflag &= ~CSTOPB;
switch (stopBits) {
- case 0: /* One */
- /* do nothing, the default is one stop bit */
+ case NoneStopBits:
+ /* Unhandled */
break;
- case 1: /* OnePointFive */
- /* XXX unhandled */
+ case One: /* One */
+ /* do nothing, the default is one stop bit */
break;
- case 2: /* Two */
+ case Two: /* Two */
newtio.c_cflag |= CSTOPB;
break;
+ case OnePointFive: /* OnePointFive */
+ /* XXX unhandled */
+ break;
}
newtio.c_iflag &= ~IXOFF;
newtio.c_cflag &= ~CRTSCTS;
#endif /* def CRTSCTS */
switch (handshake) {
- case 0: /* None */
+ case NoneHandshake: /* None */
/* do nothing */
break;
- case 1: /* RequestToSend (RTS) */
+ case RequestToSend: /* RequestToSend (RTS) */
#ifdef CRTSCTS
newtio.c_cflag |= CRTSCTS;
#endif /* def CRTSCTS */
break;
- case 2: /* RequestToSendXOnXOff (RTS + XON/XOFF) */
+ case RequestToSendXOnXOff: /* RequestToSendXOnXOff (RTS + XON/XOFF) */
#ifdef CRTSCTS
newtio.c_cflag |= CRTSCTS;
#endif /* def CRTSCTS */
/* fall through */
- case 3: /* XOnXOff */
+ case XOnXOff: /* XOnXOff */
newtio.c_iflag |= IXOFF;
// newtio.c_oflag |= IXON;
break;
}
- cfsetospeed (&newtio, baud_rate);
- cfsetispeed (&newtio, baud_rate);
-
- tcsetattr(fd,TCSADRAIN,&newtio);
+ if (cfsetospeed (&newtio, baud_rate) < 0 || cfsetispeed (&newtio, baud_rate) < 0 ||
+ tcsetattr (fd, TCSADRAIN, &newtio) < 0)
+ return FALSE;
return TRUE;
}
+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;
+}
+
+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;
+}
+
/*
* mono internals should not be used here.
* this serial stuff needs to be implemented with icalls.