Revert 67496 as it makes running Paint.NET impossible
[mono.git] / support / serial.c
index e4dfcc0a4c8265ace54196b7f05ff8b49d55b96e..34d3943142d064db85829fb41129aef88ee0092d 100644 (file)
 #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,
@@ -41,11 +47,12 @@ typedef enum {
 
 /* This is a copy of System.IO.Ports.SerialSignal */
 typedef enum {
-       Cd = 0, /* Carrier detect */
-       Cts = 1, /* Clear to send */
-       Dsr = 2, /* Data set ready */
-       Dtr = 3, /* Data terminal ready */
-       Rts = 4  /* Request to send */
+       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
@@ -67,8 +74,6 @@ open_serial (char* devfile)
        tcflush(fd, TCIOFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);
 
-       fcntl (fd, F_SETFL, O_NONBLOCK);
-
        return fd;
 }
 
@@ -79,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);
 
@@ -123,6 +118,18 @@ 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, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake)
 {
@@ -249,22 +256,46 @@ get_signal_code (MonoSerialSignal signal)
                        return TIOCM_DTR;
                case Rts:
                        return TIOCM_RTS;
+               default:
+                       return 0;
        }
 
        /* Not reached */
        return 0;
 }
 
-gint32
-get_signal (int fd, MonoSerialSignal signal)
+static MonoSerialSignal
+get_mono_signal_codes (int signals)
 {
-       int signals, expected;
+       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;
+}
 
-       expected = get_signal_code (signal);
-       if (ioctl (fd, TIOCMGET, &signals) == -1)
-               return -1;
+MonoSerialSignal
+get_signals (int fd, gint32 *error)
+{
+       int signals;
+
+       *error = 0;
+       
+       if (ioctl (fd, TIOCMGET, &signals) == -1) {
+               *error = -1;
+               return NoneSignal;
+       }
        
-       return (expected & signals) != 0;
+       return get_mono_signal_codes (signals);
 }
 
 gint32
@@ -291,6 +322,28 @@ set_signal (int fd, MonoSerialSignal signal, gboolean value)
        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.