diff options
Diffstat (limited to 'gr-fcd/lib/hid/hid-libusb.c')
-rw-r--r-- | gr-fcd/lib/hid/hid-libusb.c | 174 |
1 files changed, 87 insertions, 87 deletions
diff --git a/gr-fcd/lib/hid/hid-libusb.c b/gr-fcd/lib/hid/hid-libusb.c index 7069f50d0..82cbc9151 100644 --- a/gr-fcd/lib/hid/hid-libusb.c +++ b/gr-fcd/lib/hid/hid-libusb.c @@ -10,7 +10,7 @@ Libusb Version - 8/13/2010 Copyright 2009, All Rights Reserved. - + At the discretion of the user of this library, this software may be licensed under the terms of the GNU Public License v3, a BSD-Style license, or the @@ -77,23 +77,23 @@ struct input_report { struct hid_device_ { /* Handle to the actual device. */ libusb_device_handle *device_handle; - + /* Endpoint information */ int input_endpoint; int output_endpoint; int input_ep_max_packet_size; - /* The interface number of the HID */ + /* The interface number of the HID */ int interface; - + /* Indexes of Strings */ int manufacturer_index; int product_index; int serial_index; - + /* Whether blocking reads are used */ int blocking; /* boolean */ - + /* Read thread objects */ pthread_t thread; pthread_mutex_t mutex; /* Protects input_reports */ @@ -126,11 +126,11 @@ static hid_device *new_hid_device(void) dev->shutdown_thread = 0; dev->transfer = NULL; dev->input_reports = NULL; - + pthread_mutex_init(&dev->mutex, NULL); pthread_cond_init(&dev->condition, NULL); pthread_barrier_init(&dev->barrier, NULL, 2); - + return dev; } @@ -191,13 +191,13 @@ static int get_usage(uint8_t *report_descriptor, size_t size, int size_code; int data_len, key_size; int usage_found = 0, usage_page_found = 0; - + while (i < size) { int key = report_descriptor[i]; int key_cmd = key & 0xfc; //printf("key: %02hhx\n", key); - + if ((key & 0xf0) == 0xf0) { /* This is a Long Item. The next byte contains the length of the data section (value) for this key. @@ -232,7 +232,7 @@ static int get_usage(uint8_t *report_descriptor, size_t size, }; key_size = 1; } - + if (key_cmd == 0x4) { *usage_page = get_bytes(report_descriptor, size, data_len, i); usage_page_found = 1; @@ -246,11 +246,11 @@ static int get_usage(uint8_t *report_descriptor, size_t size, if (usage_page_found && usage_found) return 0; /* success */ - + /* Skip over this key and it's associated data */ i += data_len + key_size; } - + return -1; /* failure */ } #endif // INVASIVE_GET_USAGE @@ -262,7 +262,7 @@ static uint16_t get_first_language(libusb_device_handle *dev) { uint16_t buf[32]; int len; - + /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, 0x0, /* String ID */ @@ -271,7 +271,7 @@ static uint16_t get_first_language(libusb_device_handle *dev) sizeof(buf)); if (len < 4) return 0x0; - + return buf[1]; // First two bytes are len and descriptor type. } @@ -280,7 +280,7 @@ static int is_language_supported(libusb_device_handle *dev, uint16_t lang) uint16_t buf[32]; int len; int i; - + /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, 0x0, /* String ID */ @@ -289,8 +289,8 @@ static int is_language_supported(libusb_device_handle *dev, uint16_t lang) sizeof(buf)); if (len < 4) return 0x0; - - + + len /= 2; /* language IDs are two-bytes each. */ /* Start at index 1 because there are two bytes of protocol data. */ for (i = 1; i < len; i++) { @@ -325,7 +325,7 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) lang = get_usb_code_for_current_locale(); if (!is_language_supported(dev, lang)) lang = get_first_language(dev); - + /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, idx, @@ -334,17 +334,17 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) sizeof(buf)); if (len < 0) return NULL; - + buf[sizeof(buf)-1] = '\0'; - + if (len+1 < sizeof(buf)) buf[len+1] = '\0'; - + /* Initialize iconv. */ ic = iconv_open("UTF-32", "UTF-16"); if (ic == (iconv_t)-1) return NULL; - + /* Convert to UTF-32 (wchar_t on glibc systems). Skip the first character (2-bytes). */ inptr = buf+2; @@ -359,13 +359,13 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; if (outbytes >= sizeof(wbuf[0])) *((wchar_t*)outptr) = 0x00000000; - + /* Allocate and copy the string. */ str = wcsdup(wbuf+1); err: iconv_close(ic); - + return str; } @@ -377,7 +377,7 @@ static char *make_path(libusb_device *dev, int interface_number) libusb_get_device_address(dev), interface_number); str[sizeof(str)-1] = '\0'; - + return strdup(str); } @@ -410,12 +410,12 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, libusb_device_handle *handle; ssize_t num_devs; int i = 0; - + struct hid_device_info *root = NULL; // return object struct hid_device_info *cur_dev = NULL; - + setlocale(LC_ALL,""); - + if (!initialized) hid_init(); @@ -431,7 +431,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, int res = libusb_get_device_descriptor(dev, &desc); unsigned short dev_vid = desc.idVendor; unsigned short dev_pid = desc.idProduct; - + /* HID's are defined at the interface level. */ if (desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) continue; @@ -462,11 +462,11 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, root = tmp; } cur_dev = tmp; - + /* Fill out the record */ cur_dev->next = NULL; cur_dev->path = make_path(dev, interface_num); - + res = libusb_open(dev, &handle); if (res >= 0) { @@ -501,7 +501,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, between interfaces. */ int detached = 0; unsigned char data[256]; - + /* Usage Page and Usage */ res = libusb_kernel_driver_active(handle, interface_num); if (res == 1) { @@ -550,7 +550,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, /* Release Number */ cur_dev->release_number = desc.bcdDevice; - + /* Interface Number */ cur_dev->interface_number = interface_num; } @@ -585,7 +585,7 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, wchar struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; - + devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { @@ -611,14 +611,14 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, wchar } hid_free_enumeration(devs); - + return handle; } static void read_callback(struct libusb_transfer *transfer) { hid_device *dev = transfer->user_data; - + if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { struct input_report *rpt = malloc(sizeof(*rpt)); @@ -644,13 +644,13 @@ static void read_callback(struct libusb_transfer *transfer) num_queued++; } cur->next = rpt; - + /* Pop one off if we've reached 30 in the queue. This way we don't grow forever if the user never reads anything from the device. */ if (num_queued > 30) { return_data(dev, NULL, 0); - } + } } pthread_mutex_unlock(&dev->mutex); } @@ -668,7 +668,7 @@ static void read_callback(struct libusb_transfer *transfer) else { LOG("Unknown transfer code: %d\n", transfer->status); } - + /* Re-submit the transfer object. */ libusb_submit_transfer(transfer); } @@ -691,14 +691,14 @@ static void *read_thread(void *param) read_callback, dev, 5000/*timeout*/); - + /* Make the first submission. Further submissions are made from inside read_callback() */ libusb_submit_transfer(dev->transfer); // Notify the main thread that the read thread is up and running. pthread_barrier_wait(&dev->barrier); - + /* Handle all the events. */ while (!dev->shutdown_thread) { int res; @@ -708,14 +708,14 @@ static void *read_thread(void *param) break; } } - + /* Cancel any transfer that may be pending. This call will fail if no transfers are pending, but that's OK. */ if (libusb_cancel_transfer(dev->transfer) == 0) { /* The transfer was cancelled, so wait for its completion. */ libusb_handle_events(NULL); } - + /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to make sure that a thread which is about to go to sleep waiting on @@ -732,7 +732,7 @@ static void *read_thread(void *param) cleaned up after the call to pthread_join() (in hid_close()), but since hid_close() calls libusb_cancel_transfer(), on these objects, they can not be cleaned up here. */ - + return NULL; } @@ -749,9 +749,9 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) int res; int d = 0; int good_open = 0; - + setlocale(LC_ALL,""); - + if (!initialized) hid_init(); @@ -782,7 +782,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) break; } good_open = 1; - + /* Detach the kernel driver, but only if the device is managed by the kernel */ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { @@ -795,7 +795,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) break; } } - + res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); if (res < 0) { LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); @@ -812,7 +812,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) /* Store off the interface number */ dev->interface = intf_desc->bInterfaceNumber; - + /* Find the INPUT and OUTPUT endpoints. An OUTPUT endpoint is not required. */ for (i = 0; i < intf_desc->bNumEndpoints; i++) { @@ -824,10 +824,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) int is_interrupt = (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT; - int is_output = + int is_output = (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT; - int is_input = + int is_input = (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN; @@ -844,12 +844,12 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) dev->output_endpoint = ep->bEndpointAddress; } } - + pthread_create(&dev->thread, NULL, read_thread, dev); - + // Wait here for the read thread to be initialized. pthread_barrier_wait(&dev->barrier); - + } free(dev_path); } @@ -860,7 +860,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) } libusb_free_device_list(devs, 1); - + // If we have a good handle, return it. if (good_open) { return dev; @@ -895,13 +895,13 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); - + if (res < 0) return -1; - + if (skipped_report_id) length++; - + return length; } else { @@ -912,13 +912,13 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t (unsigned char*)data, length, &actual_length, 1000); - + if (res < 0) return -1; - + if (skipped_report_id) actual_length++; - + return actual_length; } } @@ -966,14 +966,14 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t bytes_read = return_data(dev, data, length); goto ret; } - + if (dev->shutdown_thread) { /* This means the device has been disconnected. An error code of -1 should be returned. */ bytes_read = -1; goto ret; } - + if (milliseconds == -1) { /* Blocking */ while (!dev->input_reports && !dev->shutdown_thread) { @@ -994,7 +994,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t ts.tv_sec++; ts.tv_nsec -= 1000000000L; } - + while (!dev->input_reports && !dev->shutdown_thread) { res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); if (res == 0) { @@ -1002,7 +1002,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t bytes_read = return_data(dev, data, length); break; } - + /* If we're here, there was a spurious wake up or the read thread was shutdown. Run the loop again (ie: don't break). */ @@ -1039,7 +1039,7 @@ int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { dev->blocking = !nonblock; - + return 0; } @@ -1063,14 +1063,14 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); - + if (res < 0) return -1; - + /* Account for the report ID */ if (skipped_report_id) length++; - + return length; } @@ -1094,13 +1094,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); - + if (res < 0) return -1; if (skipped_report_id) res++; - + return res; } @@ -1109,31 +1109,31 @@ void HID_API_EXPORT hid_close(hid_device *dev) { if (!dev) return; - + /* Cause read_thread() to stop. */ dev->shutdown_thread = 1; libusb_cancel_transfer(dev->transfer); /* Wait for read_thread() to end. */ pthread_join(dev->thread, NULL); - + /* Clean up the Transfer objects allocated in read_thread(). */ free(dev->transfer->buffer); libusb_free_transfer(dev->transfer); - + /* release the interface */ libusb_release_interface(dev->device_handle, dev->interface); - + /* Close the handle */ libusb_close(dev->device_handle); - + /* Clear out the queue of received reports. */ pthread_mutex_lock(&dev->mutex); while (dev->input_reports) { return_data(dev, NULL, 0); } pthread_mutex_unlock(&dev->mutex); - + free_hid_device(dev); } @@ -1316,7 +1316,7 @@ static struct lang_map_entry lang_map[] = { LANG("Xhosa", "xh", 0x0434), LANG("Yiddish", "yi", 0x043D), LANG("Zulu", "zu", 0x0435), - LANG(NULL, NULL, 0x0), + LANG(NULL, NULL, 0x0), }; uint16_t get_usb_code_for_current_locale(void) @@ -1324,16 +1324,16 @@ uint16_t get_usb_code_for_current_locale(void) char *locale; char search_string[64]; char *ptr; - + /* Get the current locale. */ locale = setlocale(0, NULL); if (!locale) return 0x0; - + /* Make a copy of the current locale string. */ strncpy(search_string, locale, sizeof(search_string)); search_string[sizeof(search_string)-1] = '\0'; - + /* Chop off the encoding part, and make it lower case. */ ptr = search_string; while (*ptr) { @@ -1350,10 +1350,10 @@ uint16_t get_usb_code_for_current_locale(void) while (lang->string_code) { if (!strcmp(lang->string_code, search_string)) { return lang->usb_code; - } + } lang++; } - + /* There was no match. Find with just the language only. */ /* Chop off the variant. Chop it off at the '_'. */ ptr = search_string; @@ -1365,18 +1365,18 @@ uint16_t get_usb_code_for_current_locale(void) } ptr++; } - + #if 0 // TODO: Do we need this? /* Find the entry which matches the string code of our language. */ lang = lang_map; while (lang->string_code) { if (!strcmp(lang->string_code, search_string)) { return lang->usb_code; - } + } lang++; } #endif - + /* Found nothing. */ return 0x0; } |