From 95dd38b52a11419f28b3f2ccc40e3e33908f0836 Mon Sep 17 00:00:00 2001 From: Emmanuel Blot Date: Tue, 25 Apr 2017 19:30:17 +0200 Subject: [PATCH] Replace libusb with hidapi on macOS macOS won't let libusb access the RF2500 HID device, but hidapi does. --- Makefile | 14 ++++-- transport/rf2500hidapi.c | 105 +++++++-------------------------------- 2 files changed, 29 insertions(+), 90 deletions(-) diff --git a/Makefile b/Makefile index 21ffd72..b2a06ec 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,7 @@ else endif BSLHID_OBJ ?= transport/bslhid.o +RF25000_OBJ ?= transport/rf2500.o ifeq ($(OS),Windows_NT) MSPDEBUG_CC = $(CC) @@ -66,13 +67,18 @@ else ifeq ($(UNAME_S),Darwin) # Mac OS X/MacPorts stuff ifeq ($(shell fink -V > /dev/null 2>&1 && echo ok),ok) - PORTS_CFLAGS := $(shell pkg-config --cflags libusb) - PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread + PORTS_CFLAGS := $(shell pkg-config --cflags hidapi libusb) + PORTS_LDFLAGS := $(shell pkg-config --libs hidapi libusb) -ltermcap -pthread + else ifeq ($(shell brew --version > /dev/null 2>&1 && echo ok),ok) + PORTS_CFLAGS := $(shell pkg-config --cflags hidapi) + PORTS_LDFLAGS := $(shell pkg-config --libs hidapi) -framework IOKit -framework CoreFoundation else PORTS_CFLAGS := -I/opt/local/include - PORTS_LDFLAGS := -L/opt/local/lib -framework IOKit -framework CoreFoundation + PORTS_LDFLAGS := -L/opt/local/lib -lhidapi -framework IOKit -framework CoreFoundation endif BSLHID_OBJ = transport/bslosx.o + RF25000_OBJ = transport/rf2500hidapi.o + LDFLAGS = else ifneq ($(filter $(UNAME_S),OpenBSD NetBSD DragonFly),) PORTS_CFLAGS := $(shell pkg-config --cflags libusb) PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread @@ -150,10 +156,10 @@ OBJ=\ transport/cp210x.o \ transport/cdc_acm.o \ transport/ftdi.o \ - transport/rf2500.o \ transport/ti3410.o \ transport/comport.o \ $(BSLHID_OBJ) \ + $(RF25000_OBJ) \ drivers/device.o \ drivers/bsl.o \ drivers/fet.o \ diff --git a/transport/rf2500hidapi.c b/transport/rf2500hidapi.c index 468ebe4..5435ee9 100644 --- a/transport/rf2500hidapi.c +++ b/transport/rf2500hidapi.c @@ -19,11 +19,7 @@ #include #include #include -#ifndef __Windows__ -#include -#else -#include -#endif +#include #include "rf2500.h" #include "util.h" @@ -34,7 +30,7 @@ struct rf2500_transport { struct transport base; int int_number; - struct usb_dev_handle *handle; + hid_device *handle; uint8_t buf[64]; int len; @@ -59,60 +55,6 @@ struct rf2500_transport { #define USB_FET_IN_EP 0x81 #define USB_FET_OUT_EP 0x01 -static int open_interface(struct rf2500_transport *tr, - struct usb_device *dev, int ino) -{ - printc_dbg("Trying to open interface %d on %s\n", ino, dev->filename); - - tr->int_number = ino; - - tr->handle = usb_open(dev); - if (!tr->handle) { - pr_error("rf2500: can't open device"); - return -1; - } - -#if defined(__linux__) - if (usb_detach_kernel_driver_np(tr->handle, tr->int_number) < 0) - pr_error("rf2500: warning: can't " - "detach kernel driver"); -#endif - -#ifdef __Windows__ - if (usb_set_configuration(tr->handle, 1) < 0) { - pr_error("rf2500: can't set configuration 1"); - usb_close(tr->handle); - return -1; - } -#endif - - if (usb_claim_interface(tr->handle, tr->int_number) < 0) { - pr_error("rf2500: can't claim interface"); - usb_close(tr->handle); - return -1; - } - - return 0; -} - -static int open_device(struct rf2500_transport *tr, - struct usb_device *dev) -{ - struct usb_config_descriptor *c = &dev->config[0]; - int i; - - for (i = 0; i < c->bNumInterfaces; i++) { - struct usb_interface *intf = &c->interface[i]; - struct usb_interface_descriptor *desc = &intf->altsetting[0]; - - if (desc->bInterfaceClass == USB_FET_INTERFACE_CLASS && - !open_interface(tr, dev, desc->bInterfaceNumber)) - return 0; - } - - return -1; -} - static int usbtr_send(transport_t tr_base, const uint8_t *data, int len) { struct rf2500_transport *tr = (struct rf2500_transport *)tr_base; @@ -138,8 +80,8 @@ static int usbtr_send(transport_t tr_base, const uint8_t *data, int len) #ifdef DEBUG_USBTR debug_hexdump("USB transfer out", pbuf, txlen); #endif - if (usb_bulk_write(tr->handle, USB_FET_OUT_EP, - (char *)pbuf, txlen, 10000) < 0) { + if (hid_write(tr->handle, + (const unsigned char *)pbuf, txlen) < 0) { pr_error("rf2500: can't send data"); return -1; } @@ -157,9 +99,8 @@ static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len) int rlen; if (tr->offset >= tr->len) { - if (usb_bulk_read(tr->handle, USB_FET_IN_EP, - (char *)tr->buf, sizeof(tr->buf), - 10000) < 0) { + if (hid_read_timeout(tr->handle, (unsigned char *)tr->buf, + sizeof(tr->buf), 10000) < 0) { pr_error("rf2500: can't receive data"); return -1; } @@ -187,27 +128,23 @@ static void usbtr_destroy(transport_t tr_base) { struct rf2500_transport *tr = (struct rf2500_transport *)tr_base; - usb_release_interface(tr->handle, tr->int_number); - usb_close(tr->handle); + hid_close(tr->handle); free(tr); + hid_exit(); } static int usbtr_flush(transport_t tr_base) { struct rf2500_transport *tr = (struct rf2500_transport *)tr_base; -#if !defined(__APPLE__) && !defined(__sun__) - char buf[64]; + unsigned char buf[64]; /* Flush out lingering data. * * The timeout apparently doesn't work on OS/X, and this loop * just hangs once the endpoint buffer empties. */ - while (usb_bulk_read(tr->handle, USB_FET_IN_EP, - buf, sizeof(buf), - 100) > 0); -#endif + while (hid_read_timeout(tr->handle, buf, sizeof(buf), 100) > 0); tr->len = 0; tr->offset = 0; @@ -231,7 +168,7 @@ static const struct transport_class rf2500_transport = { transport_t rf2500_open(const char *devpath, const char *requested_serial) { struct rf2500_transport *tr = malloc(sizeof(*tr)); - struct usb_device *dev; + hid_device *handle; if (!tr) { pr_error("rf2500: can't allocate memory"); @@ -241,27 +178,23 @@ transport_t rf2500_open(const char *devpath, const char *requested_serial) memset(tr, 0, sizeof(*tr)); tr->base.ops = &rf2500_transport; - usb_init(); - usb_find_busses(); - usb_find_devices(); + hid_init(); if (devpath) - dev = usbutil_find_by_loc(devpath); + handle = hid_open_path(devpath); else - dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT, - requested_serial); + handle = hid_open(USB_FET_VENDOR, USB_FET_PRODUCT, + (wchar_t *)requested_serial); - if (!dev) { - free(tr); - return NULL; - } - - if (open_device(tr, dev) < 0) { + if (!handle) { printc_err("rf2500: failed to open RF2500 device\n"); free(tr); + hid_exit(); return NULL; } + tr->handle = handle; + usbtr_flush(&tr->base); return (transport_t)tr;