From 728ea86ecc1221001d28207d8b979fef5948e7e0 Mon Sep 17 00:00:00 2001 From: pavel Date: Sun, 11 Jan 2015 19:57:29 +0200 Subject: [PATCH] Refact. before adding OS X (1) --- README.md | 25 ++++---------- commandline/hiddata.c | 29 ++++++++++++---- commandline/hiddata.h | 77 +++++++++++++++++++++++++++---------------- 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 01fa788..4638b77 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ The big advantage of HID-based interface is that no kernel drivers and no simula The vendors currently offer only an API library for Windows, and only in binary form. We are not associated with the manufacturer(s) of these devices or author(s) of the original software offered by eBay sellers. -Our intent is to make this device usable on Linux (and any other OS that supports libusb) as well as on 64-bit Windows. +Our intent is to make this device work on Linux, 64-bit Windows and other platforms where we need it. -The main project web page is on the [V-USB wiki](http://vusb.wikidot.com/project:driver-less-usb-relays-hid-interface "driver-less-usb-relays-hid-interface"). This is because the firmware of the device is based on [V-USB](http://www.obdev.at/products/vusb/index.html). V-USB enables amazingly simple and low-cost USB hardware solutions. This repository, however, contains only the host side software. +The main project web page is on the [V-USB wiki](http://vusb.wikidot.com/project:driver-less-usb-relays-hid-interface "driver-less-usb-relays-hid-interface"). This is because the firmware of the device is based on [V-USB](http://www.obdev.at/products/vusb/index.html). V-USB enables amazingly simple and low-cost USB hardware solutions. This repository contains only the host side software. @@ -27,28 +27,17 @@ We could not locate any copyright information in the software package offered by Current state ------------- -A simple command-line utility for Linux (x86 or x64) and Windows. +A simple command-line utility for Linux (x86 or x64), Apple OS X and Windows. This is enough for our own usage. - Windows version builds with VC++ and WDK 7.1. - Linux version builds with gcc and libusb v. 0.1. Tested on RH and Ubuntu. +- OS-X 10.9+ version builds with Xcode and plain IOKit libraries. -To do: -------- - - * Reconstruct the API library, which will be binary compatible with the original software package, and minimal decent documentation. - * Move the Linux variant to newer libusb version (1.x) - * Make bindings for Python and Java - * Maybe, reconstruct the GUI utility - * Maybe, port the Windows variant to GNU (mingw) toolchain - -The original API library does not handle hot-plug and removal of USB devices. The command-line utility isn't affected by hot plug/removal, but GUI clients of the library will need to re-enumerate the devices or react to PnP events in OS-specific way. Caller must provide locking in case of accessing the library from multiple threads. - +TO-DOs, bugs and more +---------------------- -Misc. ------ +This is in the wiki and issues in the [Github project](http://git.io/bGcxrQ). -Related projects: -[USB Relay](https://github.com/johannesk/usb-relay) by Johannes Krude - complete project with hardware and firmware, based on V-USB, but not HID - so requires a driver. diff --git a/commandline/hiddata.c b/commandline/hiddata.c index 79c71bb..432533a 100644 --- a/commandline/hiddata.c +++ b/commandline/hiddata.c @@ -33,6 +33,8 @@ #ifdef _MSC_VER #pragma comment(lib, "setupapi") #pragma comment(lib, "hid") + +#define snprintf _snprintf #endif /*_MSC_VER*/ /* @@ -60,7 +62,7 @@ int usbhidGetVendorString(USBDEVHANDLE usbh, char *buffer, int len) /* Error if buffer is too short */ if ( !HidD_GetManufacturerString((HANDLE)usbh, (void*)buffer, len ) ) { DEBUG_PRINT(("error obtaining vendor name\n")); - return USBOPEN_ERR_IO; + return USBHID_ERR_IO_HID; } usbstring_to_ascii((UINT16*)buffer, buffer, len); return 0; @@ -72,7 +74,7 @@ int usbhidGetProductString(USBDEVHANDLE usbh, char *buffer, int len) /* Error if buffer is too short */ if (!HidD_GetProductString((HANDLE)usbh, (void*)buffer, len ) ) { DEBUG_PRINT(("error obtaining product name\n")); - return USBOPEN_ERR_IO; + return USBHID_ERR_IO_HID; } usbstring_to_ascii((UINT16*)buffer, buffer, len); return 0; @@ -96,7 +98,7 @@ int usbhidEnumDevices(int vendor, int product, SP_DEVICE_INTERFACE_DETAIL_DATA_W *deviceDetails = NULL; DWORD size; int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */ - int errorCode = USBOPEN_ERR_NOTFOUND; + int errorCode = USBHID_ERR_NOTFOUND; HANDLE handle = INVALID_HANDLE_VALUE; HIDD_ATTRIBUTES deviceAttributes; @@ -104,7 +106,7 @@ int usbhidEnumDevices(int vendor, int product, deviceInfoList = SetupDiGetClassDevsW(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if (!deviceInfoList || deviceInfoList == INVALID_HANDLE_VALUE) { - return USBOPEN_ERR_NOTFOUND; + return USBHID_ERR_NOTFOUND; } deviceInfo.cbSize = sizeof(deviceInfo); @@ -166,7 +168,7 @@ int usbhidSetReport(USBDEVHANDLE usbh, char *buffer, int len) { BOOLEAN rval; rval = HidD_SetFeature((HANDLE)usbh, buffer, len); - return rval == 0 ? USBOPEN_ERR_IO : 0; + return rval == 0 ? USBHID_ERR_IO_HID : 0; } @@ -175,7 +177,7 @@ int usbhidGetReport(USBDEVHANDLE usbh, int reportNumber, char *buffer, int *len) BOOLEAN rval = 0; buffer[0] = reportNumber; rval = HidD_GetFeature((HANDLE)usbh, buffer, *len); - return rval == 0 ? USBOPEN_ERR_IO : 0; + return rval == 0 ? USBHID_ERR_IO_HID : 0; } @@ -368,3 +370,18 @@ void usbhidSetUsesReportId(USBDEVHANDLE usbh) /* ######################################################################## */ #endif /* WIN32 */ /* ######################################################################## */ + +int usbhidStrerror_r( int err, char *buf, int len) +{ + const char *s; + switch (err) { + case USBHID_ERR_ACCESS: s = "Access to device denied"; + case USBHID_ERR_NOTFOUND: s = "The specified device was not found"; + case USBHID_ERR_IO: s = "Communication error with device"; + case USBHID_ERR_IO_HID: s = "HID I/O error with device"; + default: + s = ""; + } + + return snprintf(buf, len, "%s", s); +} diff --git a/commandline/hiddata.h b/commandline/hiddata.h index 6bad85a..ca8cfa5 100644 --- a/commandline/hiddata.h +++ b/commandline/hiddata.h @@ -6,34 +6,42 @@ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) */ -#ifndef __HIDDATA_H_INCLUDED__ -#define __HIDDATA_H_INCLUDED__ +#ifndef __HIDUSB_H_INCLUDED__ +#define __HIDUSB_H_INCLUDED__ /* -General Description: -This module implements an abstraction layer for data transfer over HID feature -requests. The implementation uses native Windows functions on Windows so that -no driver installation is required and libusb on Unix. You must link the -appropriate libraries in either case: "-lhid -lusb -lsetupapi" on Windows and -`libusb-config --libs` on Unix. +This module implements an abstraction layer for data transfer over HID feature requests, +mainly for use with V-USB based HID custom devices which are not keyboards, mice etc. +The implementation uses native HID API on Windows, Apple OS X +or libusb on Linux etc. + +Libraries to link are: + on Windows XP+ : -lhid -lsetupapi + on Linux or other platforms with libusb 0.1: `libusb-config --libs` + on Mac OS 10.9+ : IOKit */ /* ------------------------------------------------------------------------ */ -#define USBOPEN_SUCCESS 0 /* no error */ -#define USBOPEN_ERR_ACCESS 1 /* not enough permissions to open device */ -#define USBOPEN_ERR_IO 2 /* I/O error */ -#define USBOPEN_ERR_NOTFOUND 3 /* device not found */ +#define USBHID_OK 0 /* no error */ +#define USBHID_ERR_ACCESS 1 /* access or permissions error */ +#define USBHID_ERR_IO 2 /* I/O error */ +#define USBHID_ERR_NOTFOUND 3 /* device not found */ +#define USBHID_ERR_BAD_ARG 20 /* invalid parameter */ +#define USBHID_ERR_INTERNAL 23 /* not implemented, not supported... */ +#define USBHID_ERR_IO_USB 24 /* I/O error at usb layer */ +#define USBHID_ERR_IO_HID 25 /* I/O error at hid layer */ +#define USBHID_ERR_UNKNOWN -1 /* whatever */ + /* ------------------------------------------------------------------------ */ +/* USBDEVHANDLE: Opaque handle representing the USB HID device. + */ struct usbDevice; typedef struct usbDevice usbDevice_t; -typedef usbDevice_t *USBDEVHANDLE; +typedef struct usbDevice *USBDEVHANDLE; -/* Opaque data type representing the USB device. This can be a Windows handle - * or a libusb handle, depending on the backend implementation. - */ /* ------------------------------------------------------------------------ */ @@ -42,13 +50,15 @@ typedef usbDevice_t *USBDEVHANDLE; * Each found device is opened and the callback will be called. * The callback can probe the device and close it or keep open. * If the callback returns 0, enumeration stops, else it goes on. - * @returns 0 if some devices were found or error code otherwise. + * @param usbhidEnumFunc: callback function + * @param context: context pointer for the callback + * @return 0 if some devices were found or error code otherwise. */ int usbhidEnumDevices(int vendorID, int productID, void *context, int (*usbhidEnumFunc)(USBDEVHANDLE usbh, void *ctx)); /* - * Close USB device handle opened with usbhidEnumDevices + * Close USBDEVHANDLE passed by usbhidEnumDevices */ void usbhidCloseDevice(USBDEVHANDLE usbh); @@ -60,24 +70,33 @@ void usbhidCloseDevice(USBDEVHANDLE usbh); int usbhidGetVendorString(USBDEVHANDLE usbh, char *buffer, int len); int usbhidGetProductString(USBDEVHANDLE usbh, char *buffer, int len); -int usbhidSetReport(usbDevice_t *device, char *buffer, int len); -/* This function sends a feature report to the device. The report ID must be - * in the first byte of buffer and the length 'len' of the report is specified - * including this report ID. If no report IDs are used, buffer[0] must be set - * to 0 (dummy report ID). - * Returns: 0 on success, an error code otherwise. +/* Send a feature report to the device. The report ID must be + * in the first byte of buffer and the length 'len' of the report buffer + * includes this report ID. If the device does not specify report IDs, + * buffer[0] must be set to 0. + * @return: 0 on success, an error code otherwise. */ +int usbhidSetReport(USBDEVHANDLE usbh, char *buffer, int len); -int usbhidGetReport(usbDevice_t *device, int reportID, char *buffer, int *len); -/* This function obtains a feature report from the device. The requested - * report-ID is passed in 'reportID'. The caller must pass a buffer of the size - * of the expected report in 'buffer' and initialize the variable pointed to by +/* Read a feature report from the device. + * The requested report ID is passed in 'reportID' parameter and returned + * in the 1st byte of the data. + * The caller must pass a buffer of the size of the expected report in 'buffer' + * including the report id byte, and initialize the variable pointed to by * 'len' to the total size of this buffer. Upon successful return, the report * (prefixed with the report-ID) is in 'buffer' and the actual length of the * report is returned in '*len'. * Returns: 0 on success, an error code otherwise. */ +int usbhidGetReport(USBDEVHANDLE usbh, int reportID, char *buffer, int *len); + + +/** + * Return description of error code + * TODO? return error descr. of underlying libusb or hid layer too? + */ +int usbhidStrerror_r( int err, char *buf, int len); /* ------------------------------------------------------------------------ */ -#endif /* __HIDDATA_H_INCLUDED__ */ +#endif /* __HIDUSB_H_INCLUDED__ */ -- 2.25.1