X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=support%2Fserial.c;h=34d3943142d064db85829fb41129aef88ee0092d;hb=444f1ae2c091de3ce8646fcd5be4479a46deb1d4;hp=8ae46b8a6bfcfd110ee0e63d4bfd512854d1668e;hpb=38f320d19a29a3e7d6a92cdb0b3ebec149d7c1a7;p=mono.git diff --git a/support/serial.c b/support/serial.c index 8ae46b8a6bf..34d3943142d 100644 --- a/support/serial.c +++ b/support/serial.c @@ -10,9 +10,51 @@ #include #include #include +#include +#include #include +/* This is for FIONREAD on solaris */ +#if defined(sun) +#include +#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) { @@ -32,8 +74,6 @@ open_serial (char* devfile) tcflush(fd, TCIOFLUSH); tcsetattr(fd,TCSANOW,&newtio); - fcntl (fd, F_SETFL, O_NONBLOCK); - return fd; } @@ -44,19 +84,9 @@ close_serial (int unix_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); @@ -88,8 +118,20 @@ discard_buffer (int fd, gboolean input) 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; @@ -121,22 +163,22 @@ set_attributes (int fd, int baud_rate, int parity, int dataBits, int stopBits, i } 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; } @@ -154,15 +196,18 @@ set_attributes (int fd, int baud_rate, int parity, int dataBits, int stopBits, i 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; @@ -171,33 +216,134 @@ set_attributes (int fd, int baud_rate, int parity, int dataBits, int stopBits, i 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; + + if (poll (&pinfo, 1, timeout) == -1) { + /* EINTR is an OK condition, we should not throw in the upper layer an IOException */ + if (errno == EINTR) + return FALSE; + *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.