mirror of
https://github.com/RPCS3/hidapi.git
synced 2026-07-21 00:45:21 -04:00
Merge branch 'master' of github.com:signal11/hidapi
This commit is contained in:
+5
-5
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user