From aa3d51925adbc54eef2ace00605673a75d95c346 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Sat, 24 Jul 2010 11:05:36 -0400 Subject: [PATCH] Changed the interface to use a pointer instead of an int as the device handle. This is only implemented on Linux so far. --- hidapi/hidapi.h | 45 +++++----- linux/hid.c | 208 ++++++++++------------------------------------- testgui/test.cpp | 19 +++-- 3 files changed, 77 insertions(+), 195 deletions(-) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index 04b2e5a..1ce277d 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -27,7 +27,10 @@ #ifdef __cplusplus extern "C" { #endif - struct hid_device { + struct hid_device_; + typedef struct hid_device_ hid_device; + + struct hid_device_info { /** Platform-specific device path */ char *path; /** Device Vendor ID */ @@ -42,7 +45,7 @@ extern "C" { wchar_t *product_string; /** Pointer to the next device */ - struct hid_device *next; + struct hid_device_info *next; }; @@ -62,7 +65,7 @@ extern "C" { attached to the system, or NULL in the case of failure. Free this linked list by calling hid_free_enumeration(). */ - struct hid_device HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); /** Free an enumeration Linked List This function frees a linked list created by hid_enumerate(). @@ -75,7 +78,7 @@ extern "C" { This function does not return a value. */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device *devs); + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); /** Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number. If serial_number is NULL, the first @@ -88,10 +91,10 @@ extern "C" { (Optionally NULL). Return: - This function returns a small integer handle on success - and -1 on failure. + This function returns a pointer to a hid_device object on + success or NULL on failure. */ - int HID_API_EXPORT HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number); + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number); /** Open a HID device by its path name. The path name be determined by calling hid_enumerate(), or a platform-specific path name can @@ -101,10 +104,10 @@ extern "C" { path: The path name of the device to open Return: - This function returns a small integer handle on success - and -1 on failure. + This function returns a pointer to a hid_device object on + success or NULL on failure. */ - int HID_API_EXPORT HID_API_CALL hid_open_path(const char *path); + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); /** Write an Output report to a HID device. The first byte of data[] must contain the Report ID. For devices which only support a single @@ -130,7 +133,7 @@ extern "C" { This function returns the actual number of bytes written and -1 on error. */ - int HID_API_EXPORT HID_API_CALL hid_write(int device, const unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); /** Read an Input report from a HID device. Input reports are returned to the host through the INTERRUPT IN endpoint. The first byte will @@ -147,7 +150,7 @@ extern "C" { This function returns the actual number of bytes read and -1 on error. */ - int HID_API_EXPORT HID_API_CALL hid_read(int device, unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); /** Set the device handle to be non-blocking. In non-blocking mode calls to hid_read() will return immediately with a value of 0 @@ -164,7 +167,7 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(int device, int nonblock); + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); /** Send a Feature report to the device. Feature reports are sent over the Control endpoint as a Set_Report transfer. The first @@ -189,7 +192,7 @@ extern "C" { This function returns the actual number of bytes written and -1 on error. */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(int device, const unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); /** Get a feature report from a HID device. Make sure to set the first byte of data[] to the Report ID of the report to be read. @@ -207,14 +210,14 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(int device, unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); /** Close a HID device. Params: device: A device handle returned from hid_open(). */ - void HID_API_EXPORT HID_API_CALL hid_close(int device); + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); /** Get The Manufacturer String from a HID device. @@ -226,7 +229,7 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(int device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); /** Get The Product String from a HID device. @@ -238,7 +241,7 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT_CALL hid_get_product_string(int device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); /** Get The Serial Number String from a HID device. @@ -250,7 +253,7 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(int device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); /** Get a string from a HID device, based on its string index. @@ -263,7 +266,7 @@ extern "C" { Return Value: This function returns 0 on success and -1 on error. */ - int HID_API_EXPORT_CALL hid_get_indexed_string(int device, int string_index, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); /** Get a string describing the last error which occurred. @@ -274,7 +277,7 @@ extern "C" { This function returns a string containing the last error which occurred or NULL if none has occurred. */ - HID_API_EXPORT const char* HID_API_CALL hid_error(int device); + HID_API_EXPORT const char* HID_API_CALL hid_error(hid_device *device); #ifdef __cplusplus } diff --git a/linux/hid.c b/linux/hid.c index 992bdee..7ad54bc 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -35,20 +35,26 @@ #include "hidapi.h" -struct Device { - int valid; +struct hid_device_ { int device_handle; int blocking; int uses_numbered_reports; }; -#define MAX_DEVICES 64 -static struct Device devices[MAX_DEVICES]; -static int devices_initialized = 0; static __u32 kernel_version = 0; -static void register_error(struct Device *device, const char *op) +hid_device *new_hid_device() +{ + hid_device *dev = calloc(1, sizeof(hid_device)); + dev->device_handle = -1; + dev->blocking = 1; + dev->uses_numbered_reports = 0; + + return dev; +} + +static void register_error(hid_device *device, const char *op) { } @@ -83,7 +89,7 @@ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { /* Check for the Report ID key */ if (key == 0x85/*Report ID*/) { - /* This devices has a Report ID, which means it uses + /* This device has a Report ID, which means it uses numbered reports. */ return 1; } @@ -133,7 +139,7 @@ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { return 0; } -static int get_device_string(struct Device *dev, const char *key, wchar_t *string, size_t maxlen) +static int get_device_string(hid_device *dev, const char *key, wchar_t *string, size_t maxlen) { struct udev *udev; struct udev_device *udev_dev, *parent; @@ -180,15 +186,15 @@ end: } -struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) +struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; - struct hid_device *root = NULL; // return object - struct hid_device *cur_dev = NULL; + struct hid_device_info *root = NULL; // return object + struct hid_device_info *cur_dev = NULL; setlocale(LC_ALL,""); @@ -243,11 +249,11 @@ struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsig /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 && product_id == 0x0) || (vendor_id == dev_vid && product_id == dev_pid)) { - struct hid_device *tmp; + struct hid_device_info *tmp; size_t len; /* VID/PID match. Create the record. */ - tmp = malloc(sizeof(struct hid_device)); + tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } @@ -295,11 +301,11 @@ struct hid_device HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsig return root; } -void HID_API_EXPORT hid_free_enumeration(struct hid_device *devs) +void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) { - struct hid_device *d = devs; + struct hid_device_info *d = devs; while (d) { - struct hid_device *next = d->next; + struct hid_device_info *next = d->next; free(d->path); free(d->serial_number); free(d->manufacturer_string); @@ -309,11 +315,11 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device *devs) } } -int HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number) +hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, wchar_t *serial_number) { - struct hid_device *devs, *cur_dev; + struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; - int handle = -1; + hid_device *handle = NULL; devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; @@ -344,41 +350,13 @@ int HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, return handle; } -int HID_API_EXPORT hid_open_path(const char *path) +hid_device * HID_API_EXPORT hid_open_path(const char *path) { int i; - int handle = -1; - struct Device *dev = NULL; + hid_device *dev = NULL; - // Initialize the Device array if it hasn't been done. - if (!devices_initialized) { - int i; - for (i = 0; i < MAX_DEVICES; i++) { - devices[i].valid = 0; - devices[i].device_handle = -1; - devices[i].blocking = 1; - devices[i].uses_numbered_reports = 0; - } - devices_initialized = 1; - } + dev = new_hid_device(); - // Find an available handle to use; - for (i = 0; i < MAX_DEVICES; i++) { - if (!devices[i].valid) { - devices[i].valid = 1; - devices[i].device_handle = -1; - devices[i].blocking = 1; - devices[i].uses_numbered_reports = 0; - handle = i; - dev = &devices[i]; - break; - } - } - - if (handle < 0) { - return -1; - } - if (kernel_version == 0) { struct utsname name; int major, minor, release; @@ -426,46 +404,30 @@ int HID_API_EXPORT hid_open_path(const char *path) rpt_desc.size); } - return handle; + return dev; } else { // Unable to open any devices. - dev->valid = 0; - return -1; + free(dev); + return NULL; } } -int HID_API_EXPORT hid_write(int device, const unsigned char *data, size_t length) +int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { - struct Device *dev = NULL; int bytes_written; - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - bytes_written = write(dev->device_handle, data, length); return bytes_written; } -int HID_API_EXPORT hid_read(int device, unsigned char *data, size_t length) +int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { - struct Device *dev = NULL; int bytes_read; - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - bytes_read = read(dev->device_handle, data, length); if (bytes_read < 0 && errno == EAGAIN) bytes_read = 0; @@ -481,18 +443,10 @@ int HID_API_EXPORT hid_read(int device, unsigned char *data, size_t length) return bytes_read; } -int HID_API_EXPORT hid_set_nonblocking(int device, int nonblock) +int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { int flags, res; - struct Device *dev = NULL; - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - flags = fcntl(dev->device_handle, F_GETFL, 0); if (flags >= 0) { if (nonblock) @@ -513,18 +467,10 @@ int HID_API_EXPORT hid_set_nonblocking(int device, int nonblock) } -int HID_API_EXPORT hid_send_feature_report(int device, const unsigned char *data, size_t length) +int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { - struct Device *dev = NULL; int res; - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); if (res < 0) perror("ioctl (SFEATURE)"); @@ -532,18 +478,10 @@ int HID_API_EXPORT hid_send_feature_report(int device, const unsigned char *data return res; } -int HID_API_EXPORT hid_get_feature_report(int device, unsigned char *data, size_t length) +int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { - struct Device *dev = NULL; int res; - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); if (res < 0) perror("ioctl (GFEATURE)"); @@ -553,97 +491,37 @@ int HID_API_EXPORT hid_get_feature_report(int device, unsigned char *data, size_ } -void HID_API_EXPORT hid_close(int device) +void HID_API_EXPORT hid_close(hid_device *dev) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return; - if (devices[device].valid == 0) - return; - dev = &devices[device]; close(dev->device_handle); - dev->valid = 0; + free(dev); } -int HID_API_EXPORT_CALL hid_get_manufacturer_string(int device, wchar_t *string, size_t maxlen) +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - return get_device_string(dev, "manufacturer", string, maxlen); } -int HID_API_EXPORT_CALL hid_get_product_string(int device, wchar_t *string, size_t maxlen) +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - return get_device_string(dev, "product", string, maxlen); - } -int HID_API_EXPORT_CALL hid_get_serial_number_string(int device, wchar_t *string, size_t maxlen) +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - return get_device_string(dev, "serial", string, maxlen); - - return 0; } -int HID_API_EXPORT_CALL hid_get_indexed_string(int device, int string_index, wchar_t *string, size_t maxlen) +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return -1; - if (devices[device].valid == 0) - return -1; - dev = &devices[device]; - - // TODO: - return -1; } -HID_API_EXPORT const char * HID_API_CALL hid_error(int device) +HID_API_EXPORT const char * HID_API_CALL hid_error(hid_device *dev) { - struct Device *dev = NULL; - - // Get the handle - if (device < 0 || device >= MAX_DEVICES) - return NULL; - if (devices[device].valid == 0) - return NULL; - dev = &devices[device]; - - // TODO: - return NULL; } diff --git a/testgui/test.cpp b/testgui/test.cpp index e237d3c..d1b9f66 100644 --- a/testgui/test.cpp +++ b/testgui/test.cpp @@ -12,7 +12,7 @@ #include "hidapi.h" #include #include - +#include class MainWindow : public FXMainWindow { @@ -41,8 +41,8 @@ private: FXTextField *feature_text; FXText *input_text; - struct hid_device *devices; - int connected_device; + struct hid_device_info *devices; + hid_device *connected_device; protected: MainWindow() {}; @@ -82,7 +82,7 @@ MainWindow::MainWindow(FXApp *app) : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,600) { devices = NULL; - connected_device = -1; + connected_device = NULL; FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X); @@ -151,7 +151,7 @@ MainWindow::create() FXMainWindow::create(); show(); - struct hid_device *cur_dev; + struct hid_device_info *cur_dev; // List the Devices hid_free_enumeration(devices); @@ -186,7 +186,7 @@ MainWindow::create() long MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr) { - if (connected_device != -1) + if (connected_device != NULL) return 1; FXint cur_item = device_list->getCurrentItem(); @@ -195,13 +195,13 @@ MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr) FXListItem *item = device_list->getItem(cur_item); if (!item) return -1; - struct hid_device *device_info = (struct hid_device*) item->getData(); + struct hid_device_info *device_info = (struct hid_device_info*) item->getData(); if (!device_info) return -1; connected_device = hid_open_path(device_info->path); - if (connected_device < 0) { + if (!connected_device) { FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device"); return -1; } @@ -228,7 +228,7 @@ long MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr) { hid_close(connected_device); - connected_device = -1; + connected_device = NULL; connected_label->setText("Disconnected"); output_button->disable(); feature_button->disable(); @@ -303,6 +303,7 @@ MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr) } s += "\n"; input_text->appendText(s); + input_text->setBottomLine(INT_MAX); } getApp()->addTimeout(this, ID_TIMER,