update sdl Merge commit '644725478f4de0f074a6834e8423ac36dce3974f'
This commit is contained in:
289
external/sdl/SDL/src/hidapi/SDL_hidapi.c
vendored
289
external/sdl/SDL/src/hidapi/SDL_hidapi.c
vendored
@ -873,10 +873,47 @@ typedef struct LIBUSB_hid_device_ LIBUSB_hid_device;
|
||||
#undef read_thread
|
||||
#undef return_data
|
||||
|
||||
/* If the platform has any backend other than libusb, try to avoid using
|
||||
* libusb as the main backend for devices, since it detaches drivers and
|
||||
* therefore makes devices inaccessible to the rest of the OS.
|
||||
*
|
||||
* We do this by whitelisting devices we know to be accessible _exclusively_
|
||||
* via libusb; these are typically devices that look like HIDs but have a
|
||||
* quirk that requires direct access to the hardware.
|
||||
*/
|
||||
static const struct {
|
||||
Uint16 vendor;
|
||||
Uint16 product;
|
||||
} SDL_libusb_whitelist[] = {
|
||||
{ 0x057e, 0x0337 } /* Nintendo WUP-028, Wii U/Switch GameCube Adapter */
|
||||
};
|
||||
|
||||
static SDL_bool IsInWhitelist(Uint16 vendor, Uint16 product)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SDL_arraysize(SDL_libusb_whitelist); i += 1) {
|
||||
if (vendor == SDL_libusb_whitelist[i].vendor &&
|
||||
product == SDL_libusb_whitelist[i].product) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
#endif /* !SDL_HIDAPI_DISABLED */
|
||||
|
||||
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND)
|
||||
/* We have another way to get HID devices, so use the whitelist to get devices where libusb is preferred */
|
||||
#define SDL_HIDAPI_LIBUSB_WHITELIST_DEFAULT SDL_TRUE
|
||||
#else
|
||||
/* libusb is the only way to get HID devices, so don't use the whitelist, get them all */
|
||||
#define SDL_HIDAPI_LIBUSB_WHITELIST_DEFAULT SDL_FALSE
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND */
|
||||
|
||||
static SDL_bool use_libusb_whitelist = SDL_HIDAPI_LIBUSB_WHITELIST_DEFAULT;
|
||||
|
||||
/* Shared HIDAPI Implementation */
|
||||
|
||||
struct hidapi_backend
|
||||
@ -1117,6 +1154,8 @@ int SDL_hid_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
use_libusb_whitelist = SDL_GetHintBoolean("SDL_HIDAPI_LIBUSB_WHITELIST",
|
||||
SDL_HIDAPI_LIBUSB_WHITELIST_DEFAULT);
|
||||
#ifdef HAVE_LIBUSB
|
||||
if (SDL_getenv("SDL_HIDAPI_DISABLE_LIBUSB") != NULL) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
@ -1280,144 +1319,170 @@ Uint32 SDL_hid_device_change_count(void)
|
||||
return counter;
|
||||
}
|
||||
|
||||
static void AddDeviceToEnumeration(const char *driver_name, struct hid_device_info *dev, struct SDL_hid_device_info **devs, struct SDL_hid_device_info **last)
|
||||
{
|
||||
struct SDL_hid_device_info *new_dev;
|
||||
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("Adding %s device to enumeration: %ls %ls 0x%.4hx/0x%.4hx/%d",
|
||||
driver_name, dev->manufacturer_string, dev->product_string, dev->vendor_id, dev->product_id, dev->interface_number);
|
||||
#else
|
||||
(void)driver_name;
|
||||
#endif
|
||||
|
||||
new_dev = (struct SDL_hid_device_info *)SDL_malloc(sizeof(struct SDL_hid_device_info));
|
||||
if (new_dev == NULL) {
|
||||
/* Don't bother returning an error, get as many devices as possible */
|
||||
return;
|
||||
}
|
||||
CopyHIDDeviceInfo(dev, new_dev);
|
||||
|
||||
if ((*last) != NULL) {
|
||||
(*last)->next = new_dev;
|
||||
} else {
|
||||
*devs = new_dev;
|
||||
}
|
||||
*last = new_dev;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBUSB) || defined(HAVE_PLATFORM_BACKEND)
|
||||
static void RemoveDeviceFromEnumeration(const char *driver_name, struct hid_device_info *dev, struct hid_device_info **devs, void (*free_device_info)(struct hid_device_info *))
|
||||
{
|
||||
struct hid_device_info *last = NULL, *curr, *next;
|
||||
|
||||
for (curr = *devs; curr; curr = next) {
|
||||
next = curr->next;
|
||||
|
||||
if (dev->vendor_id == curr->vendor_id &&
|
||||
dev->product_id == curr->product_id &&
|
||||
(dev->interface_number < 0 || curr->interface_number < 0 || dev->interface_number == curr->interface_number)) {
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("Skipping %s device: %ls %ls 0x%.4hx/0x%.4hx/%d",
|
||||
driver_name, curr->manufacturer_string, curr->product_string, curr->vendor_id, curr->product_id, curr->interface_number);
|
||||
#else
|
||||
(void)driver_name;
|
||||
#endif
|
||||
if (last) {
|
||||
last->next = next;
|
||||
} else {
|
||||
*devs = next;
|
||||
}
|
||||
|
||||
curr->next = NULL;
|
||||
free_device_info(curr);
|
||||
continue;
|
||||
}
|
||||
last = curr;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBUSB || HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
static void RemoveNonWhitelistedDevicesFromEnumeration(struct hid_device_info **devs, void (*free_device_info)(struct hid_device_info *))
|
||||
{
|
||||
struct hid_device_info *last = NULL, *curr, *next;
|
||||
|
||||
for (curr = *devs; curr; curr = next) {
|
||||
next = curr->next;
|
||||
|
||||
if (!IsInWhitelist(curr->vendor_id, curr->product_id)) {
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("Device was not in libusb whitelist, skipping: %ls %ls 0x%.4hx/0x%.4hx/%d",
|
||||
curr->manufacturer_string, curr->product_string, curr->vendor_id, curr->product_id, curr->interface_number);
|
||||
#endif
|
||||
if (last) {
|
||||
last->next = next;
|
||||
} else {
|
||||
*devs = next;
|
||||
}
|
||||
|
||||
curr->next = NULL;
|
||||
free_device_info(curr);
|
||||
continue;
|
||||
}
|
||||
last = curr;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
#if defined(HAVE_PLATFORM_BACKEND) || defined(HAVE_DRIVER_BACKEND) || defined(HAVE_LIBUSB)
|
||||
#ifdef HAVE_LIBUSB
|
||||
struct hid_device_info *usb_devs = NULL;
|
||||
struct hid_device_info *usb_dev;
|
||||
#endif
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
struct hid_device_info *driver_devs = NULL;
|
||||
struct hid_device_info *driver_dev;
|
||||
#endif
|
||||
#ifdef HAVE_PLATFORM_BACKEND
|
||||
struct hid_device_info *usb_devs = NULL;
|
||||
struct hid_device_info *raw_devs = NULL;
|
||||
struct hid_device_info *raw_dev;
|
||||
#endif
|
||||
struct SDL_hid_device_info *devs = NULL, *last = NULL, *new_dev;
|
||||
struct hid_device_info *dev;
|
||||
struct SDL_hid_device_info *devs = NULL, *last = NULL;
|
||||
|
||||
if (SDL_hidapi_refcount == 0 && SDL_hid_init() != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Collect the available devices */
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
driver_devs = DRIVER_hid_enumerate(vendor_id, product_id);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
if (libusb_ctx.libhandle) {
|
||||
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("libusb devices found:");
|
||||
#endif
|
||||
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
|
||||
new_dev = (struct SDL_hid_device_info *)SDL_malloc(sizeof(struct SDL_hid_device_info));
|
||||
if (new_dev == NULL) {
|
||||
LIBUSB_hid_free_enumeration(usb_devs);
|
||||
SDL_hid_free_enumeration(devs);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
CopyHIDDeviceInfo(usb_dev, new_dev);
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log(" - %ls %ls 0x%.4hx 0x%.4hx",
|
||||
usb_dev->manufacturer_string, usb_dev->product_string,
|
||||
usb_dev->vendor_id, usb_dev->product_id);
|
||||
#endif
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
if (use_libusb_whitelist) {
|
||||
RemoveNonWhitelistedDevicesFromEnumeration(&usb_devs, LIBUSB_hid_free_enumeration);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
driver_devs = DRIVER_hid_enumerate(vendor_id, product_id);
|
||||
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
|
||||
new_dev = (struct SDL_hid_device_info *)SDL_malloc(sizeof(struct SDL_hid_device_info));
|
||||
CopyHIDDeviceInfo(driver_dev, new_dev);
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
}
|
||||
#endif /* HAVE_DRIVER_BACKEND */
|
||||
|
||||
#ifdef HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx) {
|
||||
raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log("hidraw devices found:");
|
||||
}
|
||||
#endif
|
||||
for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
|
||||
SDL_bool bFound = SDL_FALSE;
|
||||
#ifdef DEBUG_HIDAPI
|
||||
SDL_Log(" - %ls %ls 0x%.4hx 0x%.4hx",
|
||||
raw_dev->manufacturer_string, raw_dev->product_string,
|
||||
raw_dev->vendor_id, raw_dev->product_id);
|
||||
#endif
|
||||
#ifdef HAVE_LIBUSB
|
||||
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
|
||||
if (raw_dev->vendor_id == usb_dev->vendor_id &&
|
||||
raw_dev->product_id == usb_dev->product_id &&
|
||||
(raw_dev->interface_number < 0 || raw_dev->interface_number == usb_dev->interface_number)) {
|
||||
bFound = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
for (driver_dev = driver_devs; driver_dev; driver_dev = driver_dev->next) {
|
||||
if (raw_dev->vendor_id == driver_dev->vendor_id &&
|
||||
raw_dev->product_id == driver_dev->product_id &&
|
||||
(raw_dev->interface_number < 0 || raw_dev->interface_number == driver_dev->interface_number)) {
|
||||
bFound = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!bFound) {
|
||||
new_dev = (struct SDL_hid_device_info *)SDL_malloc(sizeof(struct SDL_hid_device_info));
|
||||
if (new_dev == NULL) {
|
||||
#ifdef HAVE_LIBUSB
|
||||
if (libusb_ctx.libhandle) {
|
||||
LIBUSB_hid_free_enumeration(usb_devs);
|
||||
}
|
||||
#endif
|
||||
PLATFORM_hid_free_enumeration(raw_devs);
|
||||
SDL_hid_free_enumeration(devs);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
CopyHIDDeviceInfo(raw_dev, new_dev);
|
||||
new_dev->next = NULL;
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
}
|
||||
/* Highest priority are custom driver devices */
|
||||
for (dev = driver_devs; dev; dev = dev->next) {
|
||||
AddDeviceToEnumeration("driver", dev, &devs, &last);
|
||||
#ifdef HAVE_LIBUSB
|
||||
RemoveDeviceFromEnumeration("libusb", dev, &usb_devs, LIBUSB_hid_free_enumeration);
|
||||
#endif
|
||||
#ifdef HAVE_PLATFORM_BACKEND
|
||||
RemoveDeviceFromEnumeration("raw", dev, &raw_devs, PLATFORM_hid_free_enumeration);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If whitelist is in effect, libusb has priority, otherwise raw devices do */
|
||||
if (use_libusb_whitelist) {
|
||||
for (dev = usb_devs; dev; dev = dev->next) {
|
||||
AddDeviceToEnumeration("libusb", dev, &devs, &last);
|
||||
#ifdef HAVE_PLATFORM_BACKEND
|
||||
RemoveDeviceFromEnumeration("raw", dev, &raw_devs, PLATFORM_hid_free_enumeration);
|
||||
#endif
|
||||
}
|
||||
PLATFORM_hid_free_enumeration(raw_devs);
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
for (dev = raw_devs; dev; dev = dev->next) {
|
||||
AddDeviceToEnumeration("platform", dev, &devs, &last);
|
||||
}
|
||||
} else {
|
||||
for (dev = raw_devs; dev; dev = dev->next) {
|
||||
AddDeviceToEnumeration("raw", dev, &devs, &last);
|
||||
#ifdef HAVE_LIBUSB
|
||||
if (libusb_ctx.libhandle) {
|
||||
LIBUSB_hid_free_enumeration(usb_devs);
|
||||
}
|
||||
RemoveDeviceFromEnumeration("libusb", dev, &usb_devs, LIBUSB_hid_free_enumeration);
|
||||
#endif
|
||||
return devs;
|
||||
}
|
||||
for (dev = usb_devs; dev; dev = dev->next) {
|
||||
AddDeviceToEnumeration("libusb", dev, &devs, &last);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || HAVE_LIBUSB */
|
||||
#ifdef HAVE_DRIVER_BACKEND
|
||||
DRIVER_hid_free_enumeration(driver_devs);
|
||||
#endif
|
||||
#ifdef HAVE_LIBUSB
|
||||
LIBUSB_hid_free_enumeration(usb_devs);
|
||||
#endif
|
||||
#ifdef HAVE_PLATFORM_BACKEND
|
||||
PLATFORM_hid_free_enumeration(raw_devs);
|
||||
#endif
|
||||
|
||||
return devs;
|
||||
}
|
||||
|
||||
void SDL_hid_free_enumeration(struct SDL_hid_device_info *devs)
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
/* #pragma push_macro/pop_macro works correctly only as of gcc >= 4.4.3
|
||||
clang-3.0 _seems_ to be OK. */
|
||||
#pragma push_macro("calloc")
|
||||
#pragma push_macro("malloc")
|
||||
#pragma push_macro("realloc")
|
||||
#pragma push_macro("free")
|
||||
@ -38,6 +39,7 @@
|
||||
#pragma push_macro("tolower")
|
||||
#pragma push_macro("wcsdup")
|
||||
|
||||
#undef calloc
|
||||
#undef malloc
|
||||
#undef realloc
|
||||
#undef free
|
||||
@ -53,6 +55,7 @@
|
||||
#undef tolower
|
||||
#undef wcsdup
|
||||
|
||||
#define calloc SDL_calloc
|
||||
#define malloc SDL_malloc
|
||||
#define realloc SDL_realloc
|
||||
#define free SDL_free
|
||||
@ -106,6 +109,7 @@ static int SDL_libusb_get_string_descriptor(libusb_device_handle *dev,
|
||||
#undef ICONV_CONST
|
||||
#undef UNDEF_ICONV_CONST
|
||||
#endif
|
||||
#pragma pop_macro("calloc")
|
||||
#pragma pop_macro("malloc")
|
||||
#pragma pop_macro("realloc")
|
||||
#pragma pop_macro("free")
|
||||
|
8
external/sdl/SDL/src/hidapi/android/hid.cpp
vendored
8
external/sdl/SDL/src/hidapi/android/hid.cpp
vendored
@ -1031,7 +1031,7 @@ extern "C"
|
||||
|
||||
int hid_init(void)
|
||||
{
|
||||
if ( !g_initialized )
|
||||
if ( !g_initialized && g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
// HIDAPI doesn't work well with Android < 4.3
|
||||
if (SDL_GetAndroidSDKVersion() >= 18) {
|
||||
@ -1040,12 +1040,6 @@ int hid_init(void)
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
|
||||
if ( !g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
LOGV( "hid_init() without callback handler" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Bluetooth is currently only used for Steam Controllers, so check that hint
|
||||
// before initializing Bluetooth, which will prompt the user for permission.
|
||||
bool init_usb = true;
|
||||
|
2
external/sdl/SDL/src/hidapi/configure.ac
vendored
2
external/sdl/SDL/src/hidapi/configure.ac
vendored
@ -74,7 +74,7 @@ case $host in
|
||||
backend="mac"
|
||||
os="darwin"
|
||||
threads="pthreads"
|
||||
LIBS="${LIBS} -framework IOKit -framework CoreFoundation -framework AppKit"
|
||||
LIBS="${LIBS} -framework IOKit -framework CoreFoundation"
|
||||
;;
|
||||
*-freebsd*)
|
||||
AC_MSG_RESULT([ (FreeBSD back-end)])
|
||||
|
@ -26,6 +26,6 @@ Pod::Spec.new do |spec|
|
||||
|
||||
spec.public_header_files = "hidapi/hidapi.h", "mac/hidapi_darwin.h"
|
||||
|
||||
spec.frameworks = "IOKit", "CoreFoundation", "AppKit"
|
||||
spec.frameworks = "IOKit", "CoreFoundation"
|
||||
|
||||
end
|
||||
|
13
external/sdl/SDL/src/hidapi/libusb/hid.c
vendored
13
external/sdl/SDL/src/hidapi/libusb/hid.c
vendored
@ -259,8 +259,16 @@ static int get_usage(uint8_t *report_descriptor, size_t size,
|
||||
//printf("Usage Page: %x\n", (uint32_t)*usage_page);
|
||||
}
|
||||
if (key_cmd == 0x8) {
|
||||
*usage = get_bytes(report_descriptor, size, data_len, i);
|
||||
usage_found = 1;
|
||||
if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */
|
||||
*usage_page = get_bytes(report_descriptor, size, 2, i + 2);
|
||||
usage_page_found = 1;
|
||||
*usage = get_bytes(report_descriptor, size, 2, i);
|
||||
usage_found = 1;
|
||||
}
|
||||
else {
|
||||
*usage = get_bytes(report_descriptor, size, data_len, i);
|
||||
usage_found = 1;
|
||||
}
|
||||
//printf("Usage: %x\n", (uint32_t)*usage);
|
||||
}
|
||||
|
||||
@ -1015,6 +1023,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||
libusb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} /* altsettings */
|
||||
} /* interfaces */
|
||||
|
130
external/sdl/SDL/src/hidapi/linux/hid.c
vendored
130
external/sdl/SDL/src/hidapi/linux/hid.c
vendored
@ -206,7 +206,7 @@ static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
|
||||
* Returns 1 if successful, 0 if an invalid key
|
||||
* Sets data_len and key_size when successful
|
||||
*/
|
||||
static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 size, int *data_len, int *key_size)
|
||||
static int get_hid_item_size(const __u8 *report_descriptor, __u32 size, unsigned int pos, int *data_len, int *key_size)
|
||||
{
|
||||
int key = report_descriptor[pos];
|
||||
int size_code;
|
||||
@ -262,7 +262,7 @@ static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 si
|
||||
* Get bytes from a HID Report Descriptor.
|
||||
* Only call with a num_bytes of 0, 1, 2, or 4.
|
||||
*/
|
||||
static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_t cur)
|
||||
static __u32 get_hid_report_bytes(const __u8 *rpt, size_t len, size_t num_bytes, size_t cur)
|
||||
{
|
||||
/* Return if there aren't enough bytes. */
|
||||
if (cur + num_bytes >= len)
|
||||
@ -285,6 +285,60 @@ static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterates until the end of a Collection.
|
||||
* Assumes that *pos is exactly at the beginning of a Collection.
|
||||
* Skips all nested Collection, i.e. iterates until the end of current level Collection.
|
||||
*
|
||||
* The return value is non-0 when an end of current Collection is found,
|
||||
* 0 when error is occured (broken Descriptor, end of a Collection is found before its begin,
|
||||
* or no Collection is found at all).
|
||||
*/
|
||||
static int hid_iterate_over_collection(const __u8 *report_descriptor, __u32 size, unsigned int *pos, int *data_len, int *key_size)
|
||||
{
|
||||
int collection_level = 0;
|
||||
|
||||
while (*pos < size) {
|
||||
int key = report_descriptor[*pos];
|
||||
int key_cmd = key & 0xfc;
|
||||
|
||||
/* Determine data_len and key_size */
|
||||
if (!get_hid_item_size(report_descriptor, size, *pos, data_len, key_size))
|
||||
return 0; /* malformed report */
|
||||
|
||||
switch (key_cmd) {
|
||||
case 0xa0: /* Collection 6.2.2.4 (Main) */
|
||||
collection_level++;
|
||||
break;
|
||||
case 0xc0: /* End Collection 6.2.2.4 (Main) */
|
||||
collection_level--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (collection_level < 0) {
|
||||
/* Broken descriptor or someone is using this function wrong,
|
||||
* i.e. should be called exactly at the collection start */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (collection_level == 0) {
|
||||
/* Found it!
|
||||
* Also possible when called not at the collection start, but should not happen if used correctly */
|
||||
return 1;
|
||||
}
|
||||
|
||||
*pos += *data_len + *key_size;
|
||||
}
|
||||
|
||||
return 0; /* Did not find the end of a Collection */
|
||||
}
|
||||
|
||||
struct hid_usage_iterator {
|
||||
unsigned int pos;
|
||||
int usage_page_found;
|
||||
unsigned short usage_page;
|
||||
};
|
||||
|
||||
/*
|
||||
* Retrieves the device's Usage Page and Usage from the report descriptor.
|
||||
* The algorithm returns the current Usage Page/Usage pair whenever a new
|
||||
@ -302,63 +356,64 @@ static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_
|
||||
* 1 when finished processing descriptor.
|
||||
* -1 on a malformed report.
|
||||
*/
|
||||
static int get_next_hid_usage(__u8 *report_descriptor, __u32 size, unsigned int *pos, unsigned short *usage_page, unsigned short *usage)
|
||||
static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage)
|
||||
{
|
||||
int data_len, key_size;
|
||||
int initial = *pos == 0; /* Used to handle case where no top-level application collection is defined */
|
||||
int usage_pair_ready = 0;
|
||||
int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */
|
||||
|
||||
/* Usage is a Local Item, it must be set before each Main Item (Collection) before a pair is returned */
|
||||
int usage_found = 0;
|
||||
|
||||
while (*pos < size) {
|
||||
int key = report_descriptor[*pos];
|
||||
while (ctx->pos < size) {
|
||||
int key = report_descriptor[ctx->pos];
|
||||
int key_cmd = key & 0xfc;
|
||||
|
||||
/* Determine data_len and key_size */
|
||||
if (!get_hid_item_size(report_descriptor, *pos, size, &data_len, &key_size))
|
||||
if (!get_hid_item_size(report_descriptor, size, ctx->pos, &data_len, &key_size))
|
||||
return -1; /* malformed report */
|
||||
|
||||
switch (key_cmd) {
|
||||
case 0x4: /* Usage Page 6.2.2.7 (Global) */
|
||||
*usage_page = get_hid_report_bytes(report_descriptor, size, data_len, *pos);
|
||||
ctx->usage_page = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos);
|
||||
ctx->usage_page_found = 1;
|
||||
break;
|
||||
|
||||
case 0x8: /* Usage 6.2.2.8 (Local) */
|
||||
*usage = get_hid_report_bytes(report_descriptor, size, data_len, *pos);
|
||||
usage_found = 1;
|
||||
if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */
|
||||
ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2);
|
||||
ctx->usage_page_found = 1;
|
||||
*usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos);
|
||||
usage_found = 1;
|
||||
}
|
||||
else {
|
||||
*usage = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos);
|
||||
usage_found = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa0: /* Collection 6.2.2.4 (Main) */
|
||||
/* A Usage Item (Local) must be found for the pair to be valid */
|
||||
if (usage_found)
|
||||
usage_pair_ready = 1;
|
||||
if (!hid_iterate_over_collection(report_descriptor, size, &ctx->pos, &data_len, &key_size)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Usage is a Local Item, unset it */
|
||||
usage_found = 0;
|
||||
break;
|
||||
/* A pair is valid - to be reported when Collection is found */
|
||||
if (usage_found && ctx->usage_page_found) {
|
||||
*usage_page = ctx->usage_page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 0x80: /* Input 6.2.2.4 (Main) */
|
||||
case 0x90: /* Output 6.2.2.4 (Main) */
|
||||
case 0xb0: /* Feature 6.2.2.4 (Main) */
|
||||
case 0xc0: /* End Collection 6.2.2.4 (Main) */
|
||||
/* Usage is a Local Item, unset it */
|
||||
usage_found = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip over this key and its associated data */
|
||||
*pos += data_len + key_size;
|
||||
|
||||
/* Return usage pair */
|
||||
if (usage_pair_ready)
|
||||
return 0;
|
||||
ctx->pos += data_len + key_size;
|
||||
}
|
||||
|
||||
/* If no top-level application collection is found and usage page/usage pair is found, pair is valid
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */
|
||||
if (initial && usage_found)
|
||||
return 0; /* success */
|
||||
if (initial && usage_found && ctx->usage_page_found) {
|
||||
*usage_page = ctx->usage_page;
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
return 1; /* finished processing */
|
||||
}
|
||||
@ -804,12 +859,14 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
|
||||
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
|
||||
if (result >= 0) {
|
||||
unsigned short page = 0, usage = 0;
|
||||
unsigned int pos = 0;
|
||||
struct hid_usage_iterator usage_iterator;
|
||||
memset(&usage_iterator, 0, sizeof(usage_iterator));
|
||||
|
||||
/*
|
||||
* Parse the first usage and usage page
|
||||
* out of the report descriptor.
|
||||
*/
|
||||
if (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) {
|
||||
if (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) {
|
||||
cur_dev->usage_page = page;
|
||||
cur_dev->usage = usage;
|
||||
}
|
||||
@ -818,7 +875,7 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device
|
||||
* Parse any additional usage and usage pages
|
||||
* out of the report descriptor.
|
||||
*/
|
||||
while (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) {
|
||||
while (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) {
|
||||
/* Create new record for additional usage pairs */
|
||||
struct hid_device_info *tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
|
||||
struct hid_device_info *prev_dev = cur_dev;
|
||||
@ -980,9 +1037,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||
|
||||
struct hidraw_report_descriptor report_desc;
|
||||
unsigned short page = 0, usage = 0;
|
||||
unsigned int pos = 0;
|
||||
if (get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc) >= 0) {
|
||||
get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage);
|
||||
struct hid_usage_iterator usage_iterator;
|
||||
memset(&usage_iterator, 0, sizeof(usage_iterator));
|
||||
get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage);
|
||||
}
|
||||
if (HIDAPI_IGNORE_DEVICE(bus_type, dev_vid, dev_pid, page, usage)) {
|
||||
continue;
|
||||
|
@ -12,7 +12,7 @@ find_package(Threads REQUIRED)
|
||||
target_link_libraries(hidapi_darwin
|
||||
PUBLIC hidapi_include
|
||||
PRIVATE Threads::Threads
|
||||
PRIVATE "-framework IOKit" "-framework CoreFoundation" "-framework AppKit"
|
||||
PRIVATE "-framework IOKit" "-framework CoreFoundation"
|
||||
)
|
||||
|
||||
set_target_properties(hidapi_darwin
|
||||
|
@ -12,7 +12,7 @@ CC=gcc
|
||||
COBJS=hid.o ../hidtest/test.o
|
||||
OBJS=$(COBJS)
|
||||
CFLAGS+=-I../hidapi -I. -Wall -g -c
|
||||
LIBS=-framework IOKit -framework CoreFoundation -framework AppKit
|
||||
LIBS=-framework IOKit -framework CoreFoundation
|
||||
|
||||
|
||||
hidtest: $(OBJS)
|
||||
|
5
external/sdl/SDL/src/hidapi/mac/hid.c
vendored
5
external/sdl/SDL/src/hidapi/mac/hid.c
vendored
@ -38,9 +38,6 @@
|
||||
|
||||
#include "hidapi_darwin.h"
|
||||
|
||||
/* As defined in AppKit.h, but we don't need the entire AppKit for a single constant. */
|
||||
extern const double NSAppKitVersionNumber;
|
||||
|
||||
/* Barrier implementation because Mac OSX doesn't have pthread_barrier.
|
||||
It also doesn't have clock_gettime(). So much for POSIX and SUSv2.
|
||||
This implementation came from Brent Priddy and was posted on
|
||||
@ -477,7 +474,7 @@ int HID_API_EXPORT hid_init(void)
|
||||
register_global_error(NULL);
|
||||
|
||||
if (!hid_mgr) {
|
||||
is_macos_10_10_or_greater = (NSAppKitVersionNumber >= 1343); /* NSAppKitVersionNumber10_10 */
|
||||
is_macos_10_10_or_greater = (kCFCoreFoundationVersionNumber >= 1151.16); /* kCFCoreFoundationVersionNumber10_10 */
|
||||
hid_darwin_set_open_exclusive(1); /* Backward compatibility */
|
||||
return init_hid_manager();
|
||||
}
|
||||
|
Reference in New Issue
Block a user