From 74440e2dbbba80b4abcc4304ddae9e484231b72d Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Tue, 1 May 2012 13:39:39 -0400 Subject: [PATCH] FreeBSD: Add FreeBSD implementation. This adds a FreeBSD implementation to HIDAPI using the libusb back-end. The libusb/ folder now contains the libusb implementation and associated Makefiles for Linux and FreeBSD. All libusb code has been removed from the linux/ folder, so that the code in libusb/ can be shared by both (and future) platforms. This commit renames linux/hid-libusb.c to libusb/hid.c. Make sure to use git log --follow to see full history of that file. This code was written by: Alex Dupre Alan Ott --- README.txt | 21 +++++++++---- libusb/.gitignore | 4 +++ libusb/Makefile | 18 +++++++++++ libusb/Makefile.freebsd | 46 ++++++++++++++++++++++++++++ libusb/Makefile.linux | 49 ++++++++++++++++++++++++++++++ linux/hid-libusb.c => libusb/hid.c | 44 ++++++++++++++++++++++----- linux/Makefile | 18 +++-------- testgui/Makefile | 4 +++ testgui/Makefile.freebsd | 33 ++++++++++++++++++++ testgui/Makefile.linux | 2 +- 10 files changed, 212 insertions(+), 27 deletions(-) create mode 100644 libusb/.gitignore create mode 100644 libusb/Makefile create mode 100644 libusb/Makefile.freebsd create mode 100644 libusb/Makefile.linux rename linux/hid-libusb.c => libusb/hid.c (96%) create mode 100644 testgui/Makefile.freebsd diff --git a/README.txt b/README.txt index 2d14317..4dc0e1a 100644 --- a/README.txt +++ b/README.txt @@ -1,17 +1,19 @@ -HID API for Windows, Linux, and Mac OS X +HID API for Windows, Linux, FreeBSD and Mac OS X About ------ HIDAPI is a multi-platform library which allows an application to interface -with USB and Bluetooth HID-Class devices on Windows, Linux, and Mac OS X. -On Windows, a DLL is built. On other platforms (and optionally on Windows), -the single source file can simply be dropped into a target application. +with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac +OS X. On Windows, a DLL is built. On other platforms (and optionally on +Windows), the single source file can simply be dropped into a target +application. HIDAPI has four back-ends: * Windows (using hid.dll) * Linux/hidraw (using the Kernel's hidraw driver) * Linux/libusb (using libusb-1.0) + * FreeBSD (using libusb-1.0) * Mac (using IOHidManager) On Linux, either the hidraw or the libusb back-end can be used. There are @@ -26,7 +28,7 @@ hidraw nodes associated with them. Keyboards, mice, and some other devices which are blacklisted from having hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw, this is not a problem. -Linux/libusb (linux/hid-libusb.c): +Linux/FreeBSD/libusb (libusb/hid-libusb.c): This back-end uses libusb-1.0 to communicate directly to a USB device. This back-end will of course not work with Bluetooth devices. @@ -110,7 +112,10 @@ To build the console test program: Windows: Build the .sln file in the windows/ directory. Linux: - cd to the linux/ directory and run make. + For the hidraw implementation, cd to the linux/ directory and run make. + For the libusb implementation, cd to the libusb/ directory and run make. + FreeBSD: + cd to the libusb/ directory and run gmake. Mac OS X: cd to the mac/ directory and run make. @@ -118,6 +123,8 @@ To build the Test GUI: The test GUI uses Fox toolkit, available from www.fox-toolkit.org. On Debian-based systems such as Ubuntu, install Fox using the following: sudo apt-get install libfox-1.6-dev + On FreeBSD, install iconv and Fox as root: + pkg_add -r gmake libiconv fox16 On Mac OSX, install Fox from ports: sudo port install fox On Windows, download the hidapi-externals.zip file from the main download @@ -132,6 +139,7 @@ To build the Test GUI: Then to build: On Windows, build the .sln file in the testgui/ directory. On Linux and Mac, run make from the testgui/ directory. + On FreeBSD, run gmake from the testgui/ directory. To build using the DDK (old method): @@ -151,3 +159,4 @@ To build using the DDK (old method): Signal 11 Software - 2010-04-11 2010-07-28 2011-09-10 + 2012-05-01 diff --git a/libusb/.gitignore b/libusb/.gitignore new file mode 100644 index 0000000..ad92ec1 --- /dev/null +++ b/libusb/.gitignore @@ -0,0 +1,4 @@ +*.o +*.so +hidtest +hidtest-libusb diff --git a/libusb/Makefile b/libusb/Makefile new file mode 100644 index 0000000..c0fe868 --- /dev/null +++ b/libusb/Makefile @@ -0,0 +1,18 @@ + + +OS=$(shell uname) + +ifeq ($(OS), Linux) + FILE=Makefile.linux +endif + +ifeq ($(OS), FreeBSD) + FILE=Makefile.freebsd +endif + +ifeq ($(FILE), ) +all: + $(error Your platform ${OS} is not supported by hidapi/libusb at this time.) +endif + +include $(FILE) diff --git a/libusb/Makefile.freebsd b/libusb/Makefile.freebsd new file mode 100644 index 0000000..a94eef5 --- /dev/null +++ b/libusb/Makefile.freebsd @@ -0,0 +1,46 @@ +########################################### +# Simple Makefile for HIDAPI test program +# +# Alan Ott +# Signal 11 Software +# 2010-06-01 +########################################### + +all: hidtest libs + +libs: libhidapi.so + +CC ?= cc +CFLAGS ?= -Wall -g -fPIC + +CXX ?= c++ +CXXFLAGS ?= -Wall -g + +COBJS = hid.o +CPPOBJS = ../hidtest/hidtest.o +OBJS = $(COBJS) $(CPPOBJS) +INCLUDES = -I../hidapi -I/usr/local/include +LDFLAGS = -L/usr/local/lib +LIBS = -lusb -liconv -pthread + + +# Console Test Program +hidtest: $(OBJS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) + +# Shared Libs +libhidapi.so: $(COBJS) + $(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ + +# Objects +$(COBJS): %.o: %.c + $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ + +$(CPPOBJS): %.o: %.cpp + $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@ + + +clean: + rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o + +.PHONY: clean libs diff --git a/libusb/Makefile.linux b/libusb/Makefile.linux new file mode 100644 index 0000000..cf7b76c --- /dev/null +++ b/libusb/Makefile.linux @@ -0,0 +1,49 @@ +########################################### +# Simple Makefile for HIDAPI test program +# +# Alan Ott +# Signal 11 Software +# 2010-06-01 +########################################### + +all: hidtest-libusb libs + +libs: libhidapi-libusb.so + +CC ?= gcc +CFLAGS ?= -Wall -g -fpic + +CXX ?= g++ +CXXFLAGS ?= -Wall -g -fpic + +LDFLAGS ?= -Wall -g + +COBJS_LIBUSB = hid.o +COBJS = $(COBJS_LIBUSB) +CPPOBJS = ../hidtest/hidtest.o +OBJS = $(COBJS) $(CPPOBJS) +LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt +LIBS = $(LIBS_USB) +INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` + + +# Console Test Program +hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS) + $(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@ + +# Shared Libs +libhidapi-libusb.so: $(COBJS_LIBUSB) + $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@ + +# Objects +$(COBJS): %.o: %.c + $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ + +$(CPPOBJS): %.o: %.cpp + $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@ + + +clean: + rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o + +.PHONY: clean libs diff --git a/linux/hid-libusb.c b/libusb/hid.c similarity index 96% rename from linux/hid-libusb.c rename to libusb/hid.c index 82dafa1..df9d41f 100644 --- a/linux/hid-libusb.c +++ b/libusb/hid.c @@ -8,6 +8,7 @@ 8/22/2009 Linux Version - 6/2/2010 Libusb Version - 8/13/2010 + FreeBSD Version - 11/1/2011 Copyright 2009, All Rights Reserved. @@ -62,7 +63,7 @@ extern "C" { /* Uncomment to enable the retrieval of Usage and Usage Page in hid_enumerate(). Warning, this is very invasive as it requires the detach and re-attach of the kernel driver. See comments inside hid_enumerate(). -Linux/libusb HIDAPI programs are encouraged to use the interface number +libusb HIDAPI programs are encouraged to use the interface number instead to differentiate between interfaces on a composite HID device. */ /*#define INVASIVE_GET_USAGE*/ @@ -146,7 +147,7 @@ static void free_hid_device(hid_device *dev) } #if 0 -//TODO: Implement this funciton on Linux. +//TODO: Implement this funciton on hidapi/libusb.. static void register_error(hid_device *device, const char *op) { @@ -255,6 +256,27 @@ static int get_usage(uint8_t *report_descriptor, size_t size, } #endif // INVASIVE_GET_USAGE +#ifdef __FreeBSD__ +/* The FreeBSD version of libusb doesn't have this funciton. In mainline + libusb, it's inlined in libusb.h. This function will bear a striking + resemblence to that one, because there's about one way to code it. + + Note that the data parameter is Unicode in UTF-16LE encoding. + Return value is the number of bytes in data, or LIBUSB_ERROR_*. + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev, + uint8_t descriptor_index, uint16_t lang_id, + unsigned char *data, int length) +{ + return libusb_control_transfer(dev, + LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ + LIBUSB_REQUEST_GET_DESCRIPTOR, + (LIBUSB_DT_STRING << 8) | descriptor_index, + lang_id, data, (uint16_t) length, 1000); +} + +#endif + /* Get the first language the device says it reports. This comes from USB string #0. */ @@ -317,7 +339,11 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) size_t inbytes; size_t outbytes; size_t res; +#ifdef __FreeBSD__ + const char *inptr; +#else char *inptr; +#endif char *outptr; /* Determine which language to use. */ @@ -341,19 +367,23 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) buf[len+1] = '\0'; /* Initialize iconv. */ - ic = iconv_open("UTF-32", "UTF-16"); - if (ic == (iconv_t)-1) + ic = iconv_open("WCHAR_T", "UTF-16LE"); + if (ic == (iconv_t)-1) { + LOG("iconv_open() failed\n"); return NULL; + } - /* Convert to UTF-32 (wchar_t on glibc systems). + /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). Skip the first character (2-bytes). */ inptr = buf+2; inbytes = len-2; outptr = (char*) wbuf; outbytes = sizeof(wbuf); res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); - if (res == (size_t)-1) + if (res == (size_t)-1) { + LOG("iconv() failed\n"); goto err; + } /* Write the terminating NULL. */ wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; @@ -361,7 +391,7 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) *((wchar_t*)outptr) = 0x00000000; /* Allocate and copy the string. */ - str = wcsdup(wbuf+1); + str = wcsdup(wbuf); err: iconv_close(ic); diff --git a/linux/Makefile b/linux/Makefile index 95e9967..f731519 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -6,9 +6,9 @@ # 2010-06-01 ########################################### -all: hidtest-hidraw hidtest-libusb libs +all: hidtest-hidraw libs -libs: libhidapi-libusb.so libhidapi-hidraw.so +libs: libhidapi-hidraw.so CC ?= gcc CFLAGS ?= -Wall -g -fpic @@ -18,14 +18,12 @@ CXXFLAGS ?= -Wall -g -fpic LDFLAGS ?= -Wall -g -COBJS_LIBUSB = hid-libusb.o + COBJS_HIDRAW = hid.o -COBJS = $(COBJS_LIBUSB) $(COBJS_HIDRAW) CPPOBJS = ../hidtest/hidtest.o OBJS = $(COBJS) $(CPPOBJS) -LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt LIBS_UDEV = `pkg-config libudev --libs` -lrt -LIBS = $(LIBS_USB) $(LIBS_UDEV) +LIBS = $(LIBS_UDEV) INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` @@ -33,13 +31,7 @@ INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` hidtest-hidraw: $(COBJS_HIDRAW) $(CPPOBJS) $(CXX) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@ -hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS) - $(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@ - # Shared Libs -libhidapi-libusb.so: $(COBJS_LIBUSB) - $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@ - libhidapi-hidraw.so: $(COBJS_HIDRAW) $(CC) $(LDFLAGS) $(LIBS_UDEV) -shared -fpic -Wl,-soname,$@.0 $^ -o $@ @@ -52,6 +44,6 @@ $(CPPOBJS): %.o: %.cpp clean: - rm -f $(OBJS) hidtest-libusb hidtest-hidraw libhidapi-libusb.so libhidapi-hidraw.so ../hidtest/hidtest.o + rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so ../hidtest/hidtest.o .PHONY: clean libs diff --git a/testgui/Makefile b/testgui/Makefile index 54af870..3f61705 100644 --- a/testgui/Makefile +++ b/testgui/Makefile @@ -14,6 +14,10 @@ ifeq ($(OS), Linux) FILE=Makefile.linux endif +ifeq ($(OS), FreeBSD) + FILE=Makefile.freebsd +endif + ifeq ($(FILE), ) all: $(error Your platform ${OS} is not supported at this time.) diff --git a/testgui/Makefile.freebsd b/testgui/Makefile.freebsd new file mode 100644 index 0000000..09a2473 --- /dev/null +++ b/testgui/Makefile.freebsd @@ -0,0 +1,33 @@ +########################################### +# Simple Makefile for HIDAPI test program +# +# Alan Ott +# Signal 11 Software +# 2010-06-01 +########################################### + +all: testgui + +CC=cc +CXX=c++ +COBJS=../libusb/hid.o +CPPOBJS=test.o +OBJS=$(COBJS) $(CPPOBJS) +CFLAGS=-I../hidapi -I/usr/local/include `fox-config --cflags` -Wall -g -c +LDFLAGS= -L/usr/local/lib +LIBS= -lusb -liconv `fox-config --libs` -pthread + + +testgui: $(OBJS) + $(CXX) -Wall -g $^ $(LDFLAGS) -o $@ $(LIBS) + +$(COBJS): %.o: %.c + $(CC) $(CFLAGS) $< -o $@ + +$(CPPOBJS): %.o: %.cpp + $(CXX) $(CFLAGS) $< -o $@ + +clean: + rm *.o testgui + +.PHONY: clean diff --git a/testgui/Makefile.linux b/testgui/Makefile.linux index d84c702..80a54f2 100644 --- a/testgui/Makefile.linux +++ b/testgui/Makefile.linux @@ -10,7 +10,7 @@ all: testgui CC=gcc CXX=g++ -COBJS=../linux/hid-libusb.o +COBJS=../libusb/hid.o CPPOBJS=test.o OBJS=$(COBJS) $(CPPOBJS) CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags` `pkg-config libusb-1.0 --cflags`