]> sigrok.org Git - libserialport.git/blobdiff - serialport.c
Check return value of GetOverlappedResult().
[libserialport.git] / serialport.c
index 51eda87d4983761238fdd06721c9f150db0c4f16..b7dd66a3bfad1220d319a75fb141cae588ee47e7 100644 (file)
 #include <sys/syslimits.h>
 #endif
 #ifdef __linux__
+#ifdef HAVE_LIBUDEV
 #include "libudev.h"
+#endif
+#ifndef __ANDROID__
 #include "linux/serial.h"
+#endif
 #include "linux_termios.h"
+
+/* TCGETX/TCSETX is not available everywhere. */
 #if defined(TCGETX) && defined(TCSETX) && defined(HAVE_TERMIOX)
 #define USE_TERMIOX
 #endif
 #endif
 
+/* TIOCINQ/TIOCOUTQ is not available everywhere. */
+#if !defined(TIOCINQ) && defined(FIONREAD)
+#define TIOCINQ FIONREAD
+#endif
+#if !defined(TIOCOUTQ) && defined(FIONWRITE)
+#define TIOCOUTQ FIONWRITE
+#endif
+
 #ifndef _WIN32
 #include "linux_termios.h"
 #endif
@@ -159,7 +173,11 @@ void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
 #define RETURN_OK() RETURN_CODE(SP_OK);
 #define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
 #define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
-#define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
+#define RETURN_VALUE(fmt, x) do { \
+       typeof(x) _x = x; \
+       DEBUG("%s returning " fmt, __func__, _x); \
+       return _x; \
+} while (0)
 #define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
 #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
 #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
@@ -450,7 +468,7 @@ out_release:
        IOObjectRelease(iter);
 out_done:
 #endif
-#ifdef __linux__
+#if defined(__linux__) && defined(HAVE_LIBUDEV)
        struct udev *ud;
        struct udev_enumerate *ud_enumerate;
        struct udev_list_entry *ud_list;
@@ -799,13 +817,28 @@ enum sp_return sp_drain(struct sp_port *port)
        /* Returns non-zero upon success, 0 upon failure. */
        if (FlushFileBuffers(port->hdl) == 0)
                RETURN_FAIL("FlushFileBuffers() failed");
+       RETURN_OK();
 #else
-       /* Returns 0 upon success, -1 upon failure. */
-       if (tcdrain(port->fd) < 0)
-               RETURN_FAIL("tcdrain() failed");
+       int result;
+       while (1) {
+#ifdef __ANDROID__
+               int arg = 1;
+               result = ioctl(port->fd, TCSBRK, &arg);
+#else
+               result = tcdrain(port->fd);
+#endif
+               if (result < 0) {
+                       if (errno == EINTR) {
+                               DEBUG("tcdrain() was interrupted");
+                               continue;
+                       } else {
+                               RETURN_FAIL("tcdrain() failed");
+                       }
+               } else {
+                       RETURN_OK();
+               }
+       }
 #endif
-
-       RETURN_OK();
 }
 
 enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)
@@ -1122,7 +1155,8 @@ enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, size_t count
                RETURN_FAIL("ReadFile() failed");
 
        /* Get number of bytes read. */
-       GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
+       if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
+               RETURN_FAIL("GetOverlappedResult() failed");
 
        RETURN_VALUE("%d", bytes_read);
 #else