[Mono.Debugger.Soft] Make CommandException public
[mono.git] / support / serial.c
index 9443e0bb92301756c8d80c3db36ed31dafcec662..36b902defb93b9f12fe77e1c64afe5859db074df 100644 (file)
@@ -9,9 +9,13 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <errno.h>
+#if defined(__APPLE__)
+#include "fakepoll.h"
+#else
 #include <sys/poll.h>
+#endif
 #include <sys/ioctl.h>
-#include <errno.h>
 
 #include <glib.h>
 
@@ -60,22 +64,40 @@ typedef enum {
        Rts = 16  /* Request to send */
 } MonoSerialSignal;
 
+/*
+ * Silence the compiler, we do not need these prototypes to be public, since these are only
+ * used by P/Invoke
+ */
+
+int              open_serial (char *devfile);
+int              close_serial (int unix_fd);
+guint32          read_serial (int fd, guchar *buffer, int offset, int count);
+int              write_serial (int fd, guchar *buffer, int offset, int count, int timeout);
+int              discard_buffer (int fd, gboolean input);
+gint32           get_bytes_in_buffer (int fd, gboolean input);
+gboolean         is_baud_rate_legal (int baud_rate);
+int              setup_baud_rate (int baud_rate);
+gboolean         set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake);
+MonoSerialSignal get_signals (int fd, gint32 *error);
+gint32           set_signal (int fd, MonoSerialSignal signal, gboolean value);
+int              breakprop (int fd);
+gboolean         poll_serial (int fd, gint32 *error, int timeout);
+void            *list_serial_devices (void);
+
 int
-open_serial (chardevfile)
+open_serial (char *devfile)
 {
        int fd;
        fd = open (devfile, O_RDWR | O_NOCTTY | O_NONBLOCK);
 
-       if (fd == -1)
-               return -1;
-
        return fd;
 }
 
-void
+int
 close_serial (int unix_fd)
 {
-       close (unix_fd);
+       // Linus writes: do not retry close after EINTR
+       return close (unix_fd);
 }
 
 guint32
@@ -91,38 +113,35 @@ read_serial (int fd, guchar *buffer, int offset, int count)
 int
 write_serial (int fd, guchar *buffer, int offset, int count, int timeout)
 {
-       struct timeval tmval;
-       fd_set writefs;
+       struct pollfd pinfo;
        guint32 n;
 
-       n = count - offset;
+       pinfo.fd = fd;
+       pinfo.events = POLLOUT;
+       pinfo.revents = POLLOUT;
+
+       n = count;
 
-       FD_SET(fd, &writefs);
-       tmval.tv_sec = timeout / 1000;
-       tmval.tv_usec = (timeout - tmval.tv_sec) * 1000;        
-       
        while (n > 0)
        {
-               size_t t;
+               ssize_t t;
                        
-               if (timeout > 0)
-               {
-                       if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0 && errno != EINTR)
-                       {
+               if (timeout != 0) {
+                       int c;
+                       
+                       while ((c = poll (&pinfo, 1, timeout)) == -1 && errno == EINTR)
+                               ;
+                       if (c == -1)
                                return -1;
-                       }
                }               
 
-               t = write(fd, buffer + offset, count);
-               
-               if (timeout > 0)
-               {
-                       if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0  && errno != EINTR)
-                       {
-                               return -1;
-                       }
-       }
+               do {
+                       t = write (fd, buffer + offset, n);
+               } while (t == -1 && errno == EINTR);
 
+               if (t < 0)
+                       return -1;
+               
                offset += t;
                n -= t; 
        }
@@ -130,10 +149,10 @@ write_serial (int fd, guchar *buffer, int offset, int count, int timeout)
        return 0;
 }
 
-void
+int
 discard_buffer (int fd, gboolean input)
 {
-       tcflush(fd, input ? TCIFLUSH : TCOFLUSH);
+       return tcflush(fd, input ? TCIFLUSH : TCOFLUSH);
 }
 
 gint32
@@ -149,19 +168,27 @@ get_bytes_in_buffer (int fd, gboolean input)
 }
 
 gboolean
-set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake)
+is_baud_rate_legal (int baud_rate)
 {
-       struct termios newtio;
-
-       tcgetattr (fd, &newtio);
-       newtio.c_cflag |=  (CLOCAL | CREAD);
-       newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN );
-       newtio.c_oflag &= ~(OPOST);
-       newtio.c_iflag = IGNBRK;
+       return setup_baud_rate (baud_rate) != -1;
+}
 
-       /* setup baudrate */
+int
+setup_baud_rate (int baud_rate)
+{
        switch (baud_rate)
        {
+/*Some values are not defined on OSX and *BSD */
+#if defined(B921600)
+       case 921600:
+           baud_rate = B921600;
+           break;
+#endif
+#if defined(B460800)
+       case 460800:
+           baud_rate = B460800;
+           break;
+#endif
        case 230400: 
            baud_rate = B230400;
            break;
@@ -216,9 +243,27 @@ set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStop
        case 50:
        case 0:
        default:
-           baud_rate = B9600;
+           baud_rate = -1;
                break;
        }
+       return baud_rate;
+}
+
+gboolean
+set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake)
+{
+       struct termios newtio;
+
+       if (tcgetattr (fd, &newtio) == -1)
+               return FALSE;
+
+       newtio.c_cflag |=  (CLOCAL | CREAD);
+       newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN );
+       newtio.c_oflag &= ~(OPOST);
+       newtio.c_iflag = IGNBRK;
+
+       /* setup baudrate */
+       baud_rate = setup_baud_rate (baud_rate);
 
        /* char lenght */
        newtio.c_cflag &= ~CSIZE;
@@ -272,6 +317,7 @@ set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStop
            
        case Even: /* Even */
            newtio.c_cflag &= ~(PARODD);
+           newtio.c_cflag |= (PARENB);
            break;
            
        case Mark: /* Mark */
@@ -399,10 +445,10 @@ set_signal (int fd, MonoSerialSignal signal, gboolean value)
        return 1;
 }
 
-void
+int
 breakprop (int fd)
 {
-       tcsendbreak (fd, 0);
+       return tcsendbreak (fd, 0);
 }
 
 gboolean