diff --git a/configure.ac b/configure.ac index 016f8fa0..b3d1a0af 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,23 @@ if test "x$with_libusb" != "xno"; then LIBUSB_LIBS="-lusb-1.0" AC_DEFINE(HAVE_LIBUSB, 1, [defined if libusb is available]) have_libusb=yes + + AC_MSG_CHECKING([for libusb pollfd accessibility]) + AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include +],[ +libusb_context *ctx = NULL; +const struct libusb_pollfd** list = libusb_get_pollfds(ctx); +/* Do not care about actual return value in this test, + * normally check for non-zero meaning to look in errno */ +] + )], + [AC_DEFINE(HAVE_LIBUSB_POLLFD, 1, [defined if libusb pollfd is available]) + AC_MSG_RESULT([ok]) + ], + [AC_MSG_RESULT([no])] + ) ], [ AC_MSG_ERROR(["libusb-1.0 not found. Please install libusb-1.0."]) ]) diff --git a/src/modbus-rtu-usb.c b/src/modbus-rtu-usb.c index 5413176a..6e861767 100644 --- a/src/modbus-rtu-usb.c +++ b/src/modbus-rtu-usb.c @@ -546,7 +546,35 @@ static int _modbus_rtu_usb_connect(modbus_t *ctx) } ctx_rtu_usb->device_handle = dev_handle; - +#if defined HAVE_LIBUSB_POLLFD && HAVE_LIBUSB_POLLFD + if (usb_ctx) { + const struct libusb_pollfd** pollfds = libusb_get_pollfds(usb_ctx); + if (pollfds) { + unsigned j; + for (j=0; pollfds[j] != NULL; j++) {} + if (ctx->debug) { + printf("Got a list of %u libusb file descriptors to poll\n", j); + } + /* FIXME: We might get more than one FD here. + * Some research is needed to check if they + * all should be polled. In that case maybe + * libmodbus should move from single ctx->s + * to an array of file descriptors/sockets. + */ + if (j == 1) { + ctx->s = pollfds[0]->fd; + } + } else if (ctx->debug) { + printf("Got no list of libusb file descriptors to poll\n"); + } + } else if (ctx->debug) { + printf("Got no libusb context to query for file descriptors to poll\n"); + } +#else + if (ctx->debug) { + printf("Can not get a list of libusb file descriptors to poll from this libusb version\n"); + } +#endif /* HAVE_LIBUSB_POLLFD */ break; } diff --git a/src/modbus.c b/src/modbus.c index 0360d5cc..a350d37f 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -377,7 +377,14 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) /* Add a file descriptor to the set */ FD_ZERO(&rset); - FD_SET(ctx->s, &rset); + if (ctx->s < 0) { + if (ctx->debug) { + /* we may not have an FD with e.g. libusb usage */ + fprintf(stderr, "Using a backend without a file descriptor, will not select() on it.\n"); + } + } else { + FD_SET(ctx->s, &rset); + } /* We need to analyse the message step by step. At the first step, we want * to reach the function code because all packets contain this @@ -430,7 +437,12 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) errno = saved_errno; #endif } - return -1; + if (ctx->s >= 0) { + return -1; + } + // else: We have at most tried some default FD's but not + // the (lacking) one for the backend, so fall through for + // its recv method anyway (e.g. query libusb directly). } rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);