Use hidapi for Suunto EON Steel on Mac

libusb on Mac doesn't support HID devices.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2015-10-17 17:41:36 -07:00
parent 138fd856bd
commit 058538e628
3 changed files with 62 additions and 3 deletions

View File

@ -80,6 +80,13 @@ if test "$have_libusb" = "yes"; then
AC_SUBST([DEPENDENCIES], [libusb-1.0]) AC_SUBST([DEPENDENCIES], [libusb-1.0])
fi fi
# Checks for hidapi support.
PKG_CHECK_MODULES([HIDAPI], [hidapi], [have_hidapi=yes], [have_hidapi=no])
if test "$have_hidapi" = "yes"; then
AC_DEFINE([HAVE_HIDAPI], [1], [hidapi support])
AC_SUBST([DEPENDENCIES], [hidapi])
fi
# Checks for IrDA support. # Checks for IrDA support.
AC_CHECK_HEADERS([winsock2.h af_irda.h], [irda_win32=yes], [irda_win32=no], [ AC_CHECK_HEADERS([winsock2.h af_irda.h], [irda_win32=yes], [irda_win32=no], [
#if HAVE_WINSOCK2_H #if HAVE_WINSOCK2_H

View File

@ -1,9 +1,9 @@
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
AM_CFLAGS = $(LIBUSB_CFLAGS) AM_CFLAGS = $(LIBUSB_CFLAGS) $(HIDAPI_CFLAGS)
lib_LTLIBRARIES = libdivecomputer.la lib_LTLIBRARIES = libdivecomputer.la
libdivecomputer_la_LIBADD = $(LIBUSB_LIBS) libdivecomputer_la_LIBADD = $(LIBUSB_LIBS) $(HIDAPI_LIBS)
libdivecomputer_la_LDFLAGS = \ libdivecomputer_la_LDFLAGS = \
-version-info $(DC_VERSION_LIBTOOL) \ -version-info $(DC_VERSION_LIBTOOL) \
-no-undefined \ -no-undefined \

View File

@ -37,6 +37,9 @@
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
#if __APPLE__ && HAVE_HIDAPI
#include "hidapi/hidapi.h"
#endif
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
#ifdef _WIN32 #ifdef _WIN32
@ -49,7 +52,11 @@ typedef struct suunto_eonsteel_device_t {
dc_device_t base; dc_device_t base;
libusb_context *ctx; libusb_context *ctx;
#if __APPLE__ && HAVE_HIDAPI
hid_device *handle;
#else
libusb_device_handle *handle; libusb_device_handle *handle;
#endif
unsigned int magic; unsigned int magic;
unsigned short seq; unsigned short seq;
} suunto_eonsteel_device_t; } suunto_eonsteel_device_t;
@ -143,7 +150,12 @@ static int receive_packet(suunto_eonsteel_device_t *eon, unsigned char *buffer,
int rc, transferred, len; int rc, transferred, len;
/* 5000 = 5s timeout */ /* 5000 = 5s timeout */
#if __APPLE__ && HAVE_HIDAPI
transferred = hid_read_timeout(eon->handle, buf, PACKET_SIZE, 5000);
rc = (transferred <= 0) ? -1 : 0;
#else
rc = libusb_interrupt_transfer(eon->handle, InEndpoint, buf, PACKET_SIZE, &transferred, 5000); rc = libusb_interrupt_transfer(eon->handle, InEndpoint, buf, PACKET_SIZE, &transferred, 5000);
#endif
if (rc) { if (rc) {
ERROR(eon->base.context, "read interrupt transfer failed (%s)", libusb_error_name(rc)); ERROR(eon->base.context, "read interrupt transfer failed (%s)", libusb_error_name(rc));
return -1; return -1;
@ -209,7 +221,13 @@ static int send_cmd(suunto_eonsteel_device_t *eon,
memcpy(buf+14, buffer, len); memcpy(buf+14, buffer, len);
} }
#if __APPLE__ && HAVE_HIDAPI
/* there is no write with timeout */
transferred = hid_write(eon->handle, buf, PACKET_SIZE);
rc = (transferred <= 0) ? -1 : 0;
#else
rc = libusb_interrupt_transfer(eon->handle, OutEndpoint, buf, sizeof(buf), &transferred, 5000); rc = libusb_interrupt_transfer(eon->handle, OutEndpoint, buf, sizeof(buf), &transferred, 5000);
#endif
if (rc < 0) { if (rc < 0) {
ERROR(eon->base.context, "write interrupt transfer failed"); ERROR(eon->base.context, "write interrupt transfer failed");
return -1; return -1;
@ -530,7 +548,12 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon)
for (;;) { for (;;) {
int transferred; int transferred;
#if __APPLE__ && HAVE_HIDAPI
transferred = hid_read_timeout(eon->handle, buf, sizeof(buf), 10);
int rc = (transferred <= 0) ? -1 : 0;
#else
int rc = libusb_interrupt_transfer(eon->handle, InEndpoint, buf, sizeof(buf), &transferred, 10); int rc = libusb_interrupt_transfer(eon->handle, InEndpoint, buf, sizeof(buf), &transferred, 10);
#endif
if (rc < 0) if (rc < 0)
break; break;
if (!transferred) if (!transferred)
@ -572,6 +595,24 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, const char
// Set up the libdivecomputer interfaces // Set up the libdivecomputer interfaces
device_init(&eon->base, context, &suunto_eonsteel_device_vtable); device_init(&eon->base, context, &suunto_eonsteel_device_vtable);
#if __APPLE__ && HAVE_HIDAPI
if (hid_init()) {
ERROR(context, "hid_init() failed");
free(eon);
return DC_STATUS_IO;
}
eon->handle = hid_open(0x1493, 0x0030, NULL);
if (!eon->handle) {
ERROR(context, "unable to open device");
hid_exit();
free(eon);
return DC_STATUS_IO;
}
#else
if (libusb_init(&eon->ctx)) { if (libusb_init(&eon->ctx)) {
ERROR(context, "libusb_init() failed"); ERROR(context, "libusb_init() failed");
free(eon); free(eon);
@ -591,11 +632,16 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, const char
#endif #endif
libusb_claim_interface(eon->handle, 0); libusb_claim_interface(eon->handle, 0);
#endif
if (initialize_eonsteel(eon) < 0) { if (initialize_eonsteel(eon) < 0) {
ERROR(context, "unable to initialize device"); ERROR(context, "unable to initialize device");
#if __APPLE__ && HAVE_HIDAPI
hid_close(eon->handle);
hid_exit();
#else
libusb_close(eon->handle); libusb_close(eon->handle);
libusb_exit(eon->ctx); libusb_exit(eon->ctx);
#endif
free(eon); free(eon);
return DC_STATUS_IO; return DC_STATUS_IO;
} }
@ -688,8 +734,14 @@ suunto_eonsteel_device_close(dc_device_t *abstract)
{ {
suunto_eonsteel_device_t *eon = (suunto_eonsteel_device_t *) abstract; suunto_eonsteel_device_t *eon = (suunto_eonsteel_device_t *) abstract;
#if __APPLE__ && HAVE_HIDAPI
hid_close(eon->handle);
hid_exit();
#else
libusb_close(eon->handle); libusb_close(eon->handle);
libusb_exit(eon->ctx); libusb_exit(eon->ctx);
#endif
free(eon); free(eon);
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;