Merge branch 'master' of github.com:signal11/hidapi

This commit is contained in:
Alan Ott
2012-01-26 11:21:08 +08:00
3 changed files with 78 additions and 49 deletions
+5 -5
View File
@@ -34,11 +34,11 @@ What Does the API Look Like?
-----------------------------
The API provides the the most commonly used HID functions including sending
and receiving of input, output, and feature reports. The sample program,
which communicates with the USB Generic HID sample which is part of the
Microchip Application Library (in folder "Microchip Solutions\USB Device
- HID - Custom Demos\Generic HID - Firmware" when the Microchip Application
Framework is installed), looks like this (with error checking removed for
simplicity):
which communicates with a heavily modified version the USB Generic HID
sample which is part of the Microchip Application Library (in folder
"Microchip Solutions\USB Device - HID - Custom Demos\Generic HID - Firmware"
when the Microchip Application Framework is installed), looks like this
(with error checking removed for simplicity):
#include <windows.h>
#include <stdio.h>
+12 -15
View File
@@ -106,7 +106,7 @@ struct hid_device_ {
struct input_report *input_reports;
};
static int initialized = 0;
static libusb_context *usb_context = NULL;
uint16_t get_usb_code_for_current_locale(void);
static int return_data(hid_device *dev, unsigned char *data, size_t length);
@@ -384,10 +384,9 @@ static char *make_path(libusb_device *dev, int interface_number)
int HID_API_EXPORT hid_init(void)
{
if (!initialized) {
if (libusb_init(NULL))
if (!usb_context) {
if (libusb_init(&usb_context))
return -1;
initialized = 1;
}
return 0;
@@ -395,9 +394,9 @@ int HID_API_EXPORT hid_init(void)
int HID_API_EXPORT hid_exit(void)
{
if (initialized) {
libusb_exit(NULL);
initialized = 0;
if (usb_context) {
libusb_exit(usb_context);
usb_context = NULL;
}
return 0;
@@ -416,10 +415,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
setlocale(LC_ALL,"");
if (!initialized)
hid_init();
hid_init();
num_devs = libusb_get_device_list(NULL, &devs);
num_devs = libusb_get_device_list(usb_context, &devs);
if (num_devs < 0)
return NULL;
while ((dev = devs[i++]) != NULL) {
@@ -702,7 +700,7 @@ static void *read_thread(void *param)
/* Handle all the events. */
while (!dev->shutdown_thread) {
int res;
res = libusb_handle_events(NULL);
res = libusb_handle_events(usb_context);
if (res < 0) {
/* There was an error. Break out of this loop. */
break;
@@ -713,7 +711,7 @@ static void *read_thread(void *param)
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);
libusb_handle_events(usb_context);
}
/* Now that the read thread is stopping, Wake any threads which are
@@ -752,10 +750,9 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
setlocale(LC_ALL,"");
if (!initialized)
hid_init();
hid_init();
num_devs = libusb_get_device_list(NULL, &devs);
num_devs = libusb_get_device_list(usb_context, &devs);
while ((usb_dev = devs[d++]) != NULL) {
struct libusb_device_descriptor desc;
struct libusb_config_descriptor *conf_desc = NULL;
+61 -29
View File
@@ -263,16 +263,25 @@ static int32_t get_max_report_length(IOHIDDeviceRef device)
static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
{
CFStringRef str = IOHIDDeviceGetProperty(device, prop);
CFStringRef str;
if (!len)
return 0;
buf[0] = 0x0000;
str = IOHIDDeviceGetProperty(device, prop);
buf[0] = 0;
if (str) {
len --;
CFIndex str_len = CFStringGetLength(str);
CFRange range;
range.location = 0;
range.length = len;
range.length = (str_len > len)? len: str_len;
CFIndex used_buf_len;
CFStringGetBytes(str,
CFIndex chars_copied;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF32LE,
(char)'?',
@@ -280,8 +289,9 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
(UInt8*)buf,
len,
&used_buf_len);
buf[len-1] = 0x00000000;
return used_buf_len;
buf[chars_copied] = 0;
return chars_copied;
}
else
return 0;
@@ -290,16 +300,24 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len)
{
CFStringRef str = IOHIDDeviceGetProperty(device, prop);
CFStringRef str;
if (!len)
return 0;
buf[0] = 0x0000;
str = IOHIDDeviceGetProperty(device, prop);
buf[0] = 0;
if (str) {
len--;
CFIndex str_len = CFStringGetLength(str);
CFRange range;
range.location = 0;
range.length = len;
range.length = (str_len > len)? len: str_len;
CFIndex used_buf_len;
CFStringGetBytes(str,
CFIndex chars_copied;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF8,
(char)'?',
@@ -307,12 +325,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
(UInt8*)buf,
len,
&used_buf_len);
buf[len-1] = 0x00000000;
buf[chars_copied] = 0;
return used_buf_len;
}
else
return 0;
}
@@ -369,26 +387,32 @@ static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
return res+1;
}
/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
static int init_hid_manager(void)
{
IOReturn res;
/* Initialize all the HID Manager Objects */
hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
res = IOHIDManagerOpen(hid_mgr, kIOHIDOptionsTypeNone);
return (res == kIOReturnSuccess)? 0: -1;
if (hid_mgr) {
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
return 0;
}
return -1;
}
/* Initialize the IOHIDManager if necessary. This is the public function, and
it is safe to call this function repeatedly. Return 0 for success and -1
for failure. */
int HID_API_EXPORT hid_init(void)
{
if (!hid_mgr) {
if (init_hid_manager() < 0) {
hid_exit();
return -1;
}
return init_hid_manager();
}
/* Already initialized. */
return 0;
}
@@ -404,6 +428,13 @@ int HID_API_EXPORT hid_exit(void)
return 0;
}
static void process_pending_events() {
SInt32 res;
do {
res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
} while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut);
}
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct hid_device_info *root = NULL; // return object
@@ -414,8 +445,12 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
setlocale(LC_ALL,"");
/* Set up the HID Manager if it hasn't been done */
hid_init();
if (hid_init() < 0)
return NULL;
/* give the IOHIDManager a chance to update itself */
process_pending_events();
/* Get a list of the Devices */
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
@@ -676,13 +711,6 @@ static void *read_thread(void *param)
pthread_cond_broadcast(&dev->condition);
pthread_mutex_unlock(&dev->mutex);
/* Close the OS handle to the device, but only if it's not
been unplugged. If it's been unplugged, then calling
IOHIDDeviceClose() will crash. */
if (!dev->disconnected) {
IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeNone);
}
/* Wait here until hid_close() is called and makes it past
the call to CFRunLoopWakeUp(). This thread still needs to
be valid when that function is called on the other thread. */
@@ -700,7 +728,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
dev = new_hid_device();
/* Set up the HID Manager if it hasn't been done */
hid_init();
if (hid_init() < 0)
return NULL;
/* give the IOHIDManager a chance to update itself */
process_pending_events();
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);