Use the hidapi library on Mac OS X.

On Mac OS X, libusb doesn't work for USB HID devices. We can use the
hidapi library instead. Although the hidapi library supports Linux and
Windows too, we keep using libusb there to avoid the extra dependency.
This commit is contained in:
Jef Driesen 2016-08-18 08:25:02 +02:00
parent bae6cb856e
commit ed2a7c91fe
3 changed files with 80 additions and 12 deletions

View File

@ -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

View File

@ -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 \

View File

@ -25,11 +25,13 @@
#include <stdlib.h>
#if defined(HAVE_LIBUSB)
#if defined(HAVE_LIBUSB) && !defined(__APPLE__)
#ifdef _WIN32
#define NOGDI
#endif
#include <libusb-1.0/libusb.h>
#elif defined(HAVE_HIDAPI)
#include <hidapi/hidapi.h>
#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: