diff --git a/configure.ac b/configure.ac index b8c25dc..0bb834f 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,8 @@ esac AC_MSG_RESULT([$os_win32]) AM_CONDITIONAL([OS_WIN32], [test "$os_win32" = "yes"]) +DEPENDENCIES="" + # Checks for USB support. AC_ARG_WITH([libusb], [AS_HELP_STRING([--without-libusb], @@ -82,10 +84,25 @@ AS_IF([test "x$with_libusb" != "xno"], [ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0], [have_libusb=yes], [have_libusb=no]) AS_IF([test "x$have_libusb" = "xyes"], [ AC_DEFINE([HAVE_LIBUSB], [1], [libusb library]) - AC_SUBST([DEPENDENCIES], [libusb-1.0]) + DEPENDENCIES="$DEPENDENCIES libusb-1.0" ]) ]) +# Checks for HIDAPI support. +AC_ARG_WITH([hidapi], + [AS_HELP_STRING([--without-hidapi], + [Build without the hidapi library])], + [], [with_hidapi=auto]) +AS_IF([test "x$with_hidapi" != "xno"], [ + PKG_CHECK_MODULES([HIDAPI], [hidapi], [have_hidapi=yes], [have_hidapi=no]) + AS_IF([test "x$have_hidapi" = "xyes"], [ + AC_DEFINE([HAVE_HIDAPI], [1], [hidapi library]) + DEPENDENCIES="$DEPENDENCIES hidapi" + ]) +]) + +AC_SUBST([DEPENDENCIES]) + # Checks for IrDA support. AC_CHECK_HEADERS([winsock2.h af_irda.h], [irda_win32=yes], [irda_win32=no], [ #if HAVE_WINSOCK2_H diff --git a/src/Makefile.am b/src/Makefile.am index e52d1cd..fba41a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,9 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include -AM_CFLAGS = $(LIBUSB_CFLAGS) -DENABLE_DEPRECATED +AM_CFLAGS = $(LIBUSB_CFLAGS) $(HIDAPI_CFLAGS) -DENABLE_DEPRECATED lib_LTLIBRARIES = libdivecomputer.la -libdivecomputer_la_LIBADD = $(LIBUSB_LIBS) -lm +libdivecomputer_la_LIBADD = $(LIBUSB_LIBS) $(HIDAPI_LIBS) -lm libdivecomputer_la_LDFLAGS = \ -version-info $(DC_VERSION_LIBTOOL) \ -no-undefined \ diff --git a/src/usbhid.c b/src/usbhid.c index 1bdb1fd..f5b602d 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -25,11 +25,13 @@ #include -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) #ifdef _WIN32 #define NOGDI #endif #include +#elif defined(HAVE_HIDAPI) +#include #endif #include "usbhid.h" @@ -40,17 +42,20 @@ struct dc_usbhid_t { /* Library context. */ dc_context_t *context; /* Internal state. */ -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) libusb_context *ctx; libusb_device_handle *handle; int interface; unsigned char endpoint_in; unsigned char endpoint_out; unsigned int timeout; +#elif defined(HAVE_HIDAPI) + hid_device *handle; + int timeout; #endif }; -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) static dc_status_t syserror(int errcode) { @@ -95,7 +100,7 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi // Library context. usbhid->context = context; -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) struct libusb_device **devices = NULL; struct libusb_config_descriptor *config = NULL; @@ -226,13 +231,33 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi libusb_free_config_descriptor (config); libusb_free_device_list (devices, 1); + +#elif defined(HAVE_HIDAPI) + + // Initialize the hidapi library. + rc = hid_init(); + if (rc < 0) { + ERROR (context, "Failed to initialize usb support."); + status = DC_STATUS_IO; + goto error_free; + } + + // Open the USB device. + usbhid->handle = hid_open (vid, pid, NULL); + if (usbhid->handle == NULL) { + ERROR (context, "Failed to open the usb device."); + status = DC_STATUS_IO; + goto error_hid_exit; + } + + usbhid->timeout = -1; #endif *out = usbhid; return DC_STATUS_SUCCESS; -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) error_usb_close: libusb_close (usbhid->handle); error_usb_free_config: @@ -241,6 +266,9 @@ error_usb_free_list: libusb_free_device_list (devices, 1); error_usb_exit: libusb_exit (usbhid->ctx); +#elif defined(HAVE_HIDAPI) +error_hid_exit: + hid_exit (); #endif error_free: free (usbhid); @@ -255,10 +283,13 @@ dc_usbhid_close (dc_usbhid_t *usbhid) if (usbhid == NULL) return DC_STATUS_SUCCESS; -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) libusb_release_interface (usbhid->handle, usbhid->interface); libusb_close (usbhid->handle); libusb_exit (usbhid->ctx); +#elif defined(HAVE_HIDAPI) + hid_close(usbhid->handle); + hid_exit(); #endif free (usbhid); @@ -273,7 +304,7 @@ dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout) INFO (usbhid->context, "Timeout: value=%i", timeout); -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) if (timeout < 0) { usbhid->timeout = 0; } else if (timeout == 0) { @@ -281,6 +312,12 @@ dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout) } else { usbhid->timeout = timeout; } +#elif defined(HAVE_HIDAPI) + if (timeout < 0) { + usbhid->timeout = -1; + } else { + usbhid->timeout = timeout; + } #endif return DC_STATUS_SUCCESS; @@ -297,7 +334,7 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual) goto out; } -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_in, data, size, &nbytes, usbhid->timeout); if (rc != LIBUSB_SUCCESS) { ERROR (usbhid->context, "Usb read interrupt transfer failed (%s).", @@ -305,6 +342,13 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual) status = syserror (rc); goto out; } +#elif defined(HAVE_HIDAPI) + nbytes = hid_read_timeout(usbhid->handle, data, size, usbhid->timeout); + if (nbytes < 0) { + ERROR (usbhid->context, "Usb read interrupt transfer failed."); + status = DC_STATUS_IO; + goto out; + } #endif out: @@ -327,7 +371,7 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act goto out; } -#if defined(HAVE_LIBUSB) +#if defined(HAVE_LIBUSB) && !defined(__APPLE__) int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_out, (void *) data, size, &nbytes, 0); if (rc != LIBUSB_SUCCESS) { ERROR (usbhid->context, "Usb write interrupt transfer failed (%s).", @@ -335,6 +379,13 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act status = syserror (rc); goto out; } +#elif defined(HAVE_HIDAPI) + nbytes = hid_write(usbhid->handle, data, size); + if (nbytes < 0) { + ERROR (usbhid->context, "Usb write interrupt transfer failed."); + status = DC_STATUS_IO; + goto out; + } #endif out: