summaryrefslogtreecommitdiff
path: root/gr-fcd/lib/hid/hid-libusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fcd/lib/hid/hid-libusb.c')
-rw-r--r--gr-fcd/lib/hid/hid-libusb.c174
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;
}