Updates the SDL library to the latest standard bugfix release

This commit is contained in:
JeffR 2023-07-13 15:20:29 -05:00
parent cb766f2878
commit 083d2175ea
1280 changed files with 343926 additions and 179615 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -22,7 +22,7 @@
#ifdef SDL_JOYSTICK_HIDAPI
#ifdef SDL_LIBUSB_DYNAMIC
#ifdef HAVE_LIBUSB
#define HAVE_ENABLE_GAMECUBE_ADAPTORS
#endif

View file

@ -1085,12 +1085,25 @@ int hid_init(void)
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
struct hid_device_info *root = NULL;
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
hid_mutex_guard l( &g_DevicesMutex );
for ( hid_device_ref<CHIDDevice> pDevice = g_Devices; pDevice; pDevice = pDevice->next )
{
const hid_device_info *info = pDevice->GetDeviceInfo();
if ( ( vendor_id == 0 && product_id == 0 ) ||
( vendor_id == info->vendor_id && product_id == info->product_id ) )
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", info->vendor_id);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", info->vendor_id, info->product_id);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
continue;
}
}
if ( ( vendor_id == 0x0 || info->vendor_id == vendor_id ) &&
( product_id == 0x0 || info->product_id == product_id ) )
{
hid_device_info *dev = CopyHIDDeviceInfo( info );
dev->next = root;

View file

@ -836,9 +836,20 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{ @autoreleasepool {
struct hid_device_info *root = NULL;
if ( ( vendor_id == 0 && product_id == 0 ) ||
( vendor_id == VALVE_USB_VID && product_id == D0G_BLE2_PID ) )
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", VALVE_USB_VID);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", VALVE_USB_VID, D0G_BLE2_PID);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
return NULL;
}
}
if ( ( vendor_id == 0 || vendor_id == VALVE_USB_VID ) &&
( product_id == 0 || product_id == D0G_BLE2_PID ) )
{
HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
[bleManager updateConnectedSteamControllers:false];

View file

@ -28,8 +28,35 @@
*/
#include "../../SDL_internal.h"
#include "SDL_thread.h"
#include "../../thread/SDL_systhread.h"
#include "SDL_hints.h"
#include "SDL_mutex.h"
#include "SDL_thread.h"
#ifdef realloc
#undef realloc
#endif
#define realloc SDL_realloc
#ifdef snprintf
#undef snprintf
#endif
#define snprintf SDL_snprintf
#ifdef strdup
#undef strdup
#endif
#define strdup SDL_strdup
#ifdef strncpy
#undef strncpy
#endif
#define strncpy SDL_strlcpy
#ifdef tolower
#undef tolower
#endif
#define tolower SDL_tolower
#ifdef wcsncpy
#undef wcsncpy
#endif
#define wcsncpy SDL_wcslcpy
#ifndef HAVE_WCSDUP
#ifdef HAVE__WCSDUP
@ -51,7 +78,10 @@ static wchar_t *_dupwcs(const wchar_t *src)
#endif /* HAVE_WCSDUP */
#include <libusb.h>
#ifndef _WIN32
#define HAVE_SETLOCALE
#include <locale.h> /* setlocale */
#endif
#include "../hidapi/hidapi.h"
@ -173,6 +203,10 @@ struct hid_device_ {
int transfer_loop_finished;
struct libusb_transfer *transfer;
/* Quirks */
int skip_output_report_id;
int no_output_reports_on_intr_ep;
/* List of received input reports. */
struct input_report *input_reports;
};
@ -288,7 +322,7 @@ static int get_usage(uint8_t *report_descriptor, size_t size,
/* Can't ever happen since size_code is & 0x3 */
data_len = 0;
break;
};
}
key_size = 1;
}
@ -529,6 +563,22 @@ static struct usb_string_cache_entry *usb_string_cache_insert()
return new_entry;
}
static int usb_string_can_cache(uint16_t vid, uint16_t pid)
{
if (!vid || !pid) {
/* We can't cache these, they aren't unique */
return 0;
}
if (vid == 0x0f0d && pid == 0x00dc) {
/* HORI reuses this VID/PID for many different products */
return 0;
}
/* We can cache these strings */
return 1;
}
static const struct usb_string_cache_entry *usb_string_cache_find(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle)
{
struct usb_string_cache_entry *entry = NULL;
@ -579,16 +629,18 @@ static char *make_path(libusb_device *dev, int interface_number)
int HID_API_EXPORT hid_init(void)
{
if (!usb_context) {
const char *locale;
/* Init Libusb */
if (libusb_init(&usb_context))
return -1;
#ifdef HAVE_SETLOCALE
/* Set the locale if it's not set. */
locale = setlocale(LC_CTYPE, NULL);
if (!locale)
setlocale(LC_CTYPE, "");
{
const char *locale = setlocale(LC_CTYPE, NULL);
if (!locale)
setlocale(LC_CTYPE, "");
}
#endif
}
return 0;
@ -635,6 +687,9 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de
0x1bad, /* Harmonix */
0x20d6, /* PowerA */
0x24c6, /* PowerA */
0x2c22, /* Qanba */
0x2dc8, /* 8BitDo */
0x9886, /* ASTRO Gaming */
};
if (intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
@ -656,13 +711,16 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de
static const int XB1_IFACE_SUBCLASS = 71;
static const int XB1_IFACE_PROTOCOL = 208;
static const int SUPPORTED_VENDORS[] = {
0x044f, /* Thrustmaster */
0x045e, /* Microsoft */
0x0738, /* Mad Catz */
0x0e6f, /* PDP */
0x0f0d, /* Hori */
0x10f5, /* Turtle Beach */
0x1532, /* Razer Wildcat */
0x20d6, /* PowerA */
0x24c6, /* PowerA */
0x2dc8, /* 8BitDo */
0x2e24, /* Hyperkin */
};
@ -682,6 +740,8 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de
static int should_enumerate_interface(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
{
//printf("Checking interface 0x%x %d/%d/%d/%d\n", vendor_id, intf_desc->bInterfaceNumber, intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol);
if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID)
return 1;
@ -706,6 +766,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
struct hid_device_info *root = NULL; /* return object */
struct hid_device_info *cur_dev = NULL;
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
if(hid_init() < 0)
return NULL;
@ -723,10 +784,21 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
unsigned short dev_vid = desc.idVendor;
unsigned short dev_pid = desc.idProduct;
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", dev_vid);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", dev_vid, dev_pid);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
continue;
}
}
res = libusb_get_active_config_descriptor(dev, &conf_desc);
if (res < 0)
libusb_get_config_descriptor(dev, 0, &conf_desc);
if (conf_desc) {
for (j = 0; j < conf_desc->bNumInterfaces; j++) {
const struct libusb_interface *intf = &conf_desc->interface[j];
for (k = 0; k < intf->num_altsetting; k++) {
@ -764,7 +836,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
get_usb_string(handle, desc.iSerialNumber);
/* Manufacturer and Product strings */
if (dev_vid && dev_pid) {
if (usb_string_can_cache(dev_vid, dev_pid)) {
string_cache = usb_string_cache_find(&desc, handle);
if (string_cache) {
if (string_cache->vendor) {
@ -994,8 +1066,9 @@ static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer)
}
static int read_thread(void *param)
static int SDLCALL read_thread(void *param)
{
int res;
hid_device *dev = (hid_device *)param;
uint8_t *buf;
const size_t length = dev->input_ep_max_packet_size;
@ -1014,14 +1087,18 @@ static int read_thread(void *param)
/* Make the first submission. Further submissions are made
from inside read_callback() */
libusb_submit_transfer(dev->transfer);
res = libusb_submit_transfer(dev->transfer);
if(res < 0) {
LOG("libusb_submit_transfer failed: %d %s. Stopping read_thread from running\n", res, libusb_error_name(res));
dev->shutdown_thread = 1;
dev->transfer_loop_finished = 1;
}
/* Notify the main thread that the read thread is up and running. */
SDL_WaitThreadBarrier(&dev->barrier);
/* Handle all the events. */
while (!dev->shutdown_thread) {
int res;
res = libusb_handle_events(usb_context);
if (res < 0) {
/* There was an error. */
@ -1065,6 +1142,20 @@ static int read_thread(void *param)
return 0;
}
static void init_xbox360(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, struct libusb_config_descriptor *conf_desc)
{
if ((idVendor == 0x05ac && idProduct == 0x055b) /* Gamesir-G3w */ ||
idVendor == 0x0f0d /* Hori Xbox controllers */) {
unsigned char data[20];
/* The HORIPAD FPS for Nintendo Switch requires this to enable input reports.
This VID/PID is also shared with other HORI controllers, but they all seem
to be fine with this as well.
*/
libusb_control_transfer(device_handle, 0xC1, 0x01, 0x100, 0x0, data, sizeof(data), 100);
}
}
static void init_xboxone(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, struct libusb_config_descriptor *conf_desc)
{
static const int VENDOR_MICROSOFT = 0x045e;
@ -1110,6 +1201,19 @@ static void init_xboxone(libusb_device_handle *device_handle, unsigned short idV
}
}
static void calculate_device_quirks(hid_device *dev, unsigned short idVendor, unsigned short idProduct)
{
static const int VENDOR_SONY = 0x054c;
static const int PRODUCT_PS3_CONTROLLER = 0x0268;
static const int PRODUCT_NAVIGATION_CONTROLLER = 0x042f;
if (idVendor == VENDOR_SONY &&
(idProduct == PRODUCT_PS3_CONTROLLER || idProduct == PRODUCT_NAVIGATION_CONTROLLER)) {
dev->skip_output_report_id = 1;
dev->no_output_reports_on_intr_ep = 1;
}
}
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
{
hid_device *dev = NULL;
@ -1184,6 +1288,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
break;
}
/* Initialize XBox 360 controllers */
if (is_xbox360(desc.idVendor, intf_desc)) {
init_xbox360(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
}
/* Initialize XBox One controllers */
if (is_xboxone(desc.idVendor, intf_desc)) {
init_xboxone(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
@ -1230,7 +1339,9 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
}
}
dev->thread = SDL_CreateThread(read_thread, NULL, dev);
calculate_device_quirks(dev, desc.idVendor, desc.idProduct);
dev->thread = SDL_CreateThreadInternal(read_thread, "libusb", 0, dev);
/* Wait here for the read thread to be initialized. */
SDL_WaitThreadBarrier(&dev->barrier);
@ -1262,11 +1373,11 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
{
int res;
if (dev->output_endpoint <= 0) {
if (dev->output_endpoint <= 0 || dev->no_output_reports_on_intr_ep) {
int report_number = data[0];
int skipped_report_id = 0;
if (report_number == 0x0) {
if (report_number == 0x0 || dev->skip_output_report_id) {
data++;
length--;
skipped_report_id = 1;
@ -1709,13 +1820,15 @@ static struct lang_map_entry lang_map[] = {
uint16_t get_usb_code_for_current_locale(void)
{
char *locale;
char *locale = NULL;
char search_string[64];
char *ptr;
struct lang_map_entry *lang;
/* Get the current locale. */
#ifdef HAVE_SETLOCALE
locale = setlocale(0, NULL);
#endif
if (!locale)
return 0x0;

View file

@ -39,7 +39,7 @@ Bugs (hidraw implementation only):
-----------------------------------
On Kernel versions < 2.6.34, if your device uses numbered reports, an extra
byte will be returned at the beginning of all reports returned from read()
for hidraw devices. This is worked around in the libary. No action should be
for hidraw devices. This is worked around in the library. No action should be
necessary in the client library.
On Kernel versions < 2.6.35, reports will only be sent using a Set_Report

View file

@ -22,6 +22,8 @@
********************************************************/
#include "../../SDL_internal.h"
#include "SDL_hints.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
#endif
@ -198,7 +200,7 @@ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
/* Can't ever happen since size_code is & 0x3 */
data_len = 0;
break;
};
}
key_size = 1;
}
@ -219,7 +221,7 @@ parse_uevent_info(const char *uevent, unsigned *bus_type,
unsigned short *vendor_id, unsigned short *product_id,
char **serial_number_utf8, char **product_name_utf8)
{
char *tmp = strdup(uevent);
char *tmp;
char *saveptr = NULL;
char *line;
char *key;
@ -229,6 +231,15 @@ parse_uevent_info(const char *uevent, unsigned *bus_type,
int found_serial = 0;
int found_name = 0;
if (!uevent) {
return 0;
}
tmp = strdup(uevent);
if (!tmp) {
return 0;
}
line = strtok_r(tmp, "\n", &saveptr);
while (line != NULL) {
/* line: "KEY=value" */
@ -472,6 +483,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
struct hid_device_info *root = NULL; /* return object */
struct hid_device_info *cur_dev = NULL;
struct hid_device_info *prev_dev = NULL; /* previous device */
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
hid_init();
@ -543,6 +555,16 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
goto next;
}
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", dev_vid);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", dev_vid, dev_pid);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
continue;
}
}
/* Check the VID/PID against the arguments */
if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
(product_id == 0x0 || product_id == dev_pid)) {
@ -707,6 +729,8 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
{
const int MAX_ATTEMPTS = 10;
int attempt;
hid_device *dev = NULL;
hid_init();
@ -714,7 +738,15 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
dev = new_hid_device();
/* OPEN HERE */
dev->device_handle = open(path, O_RDWR | O_CLOEXEC);
for (attempt = 1; attempt <= MAX_ATTEMPTS; ++attempt) {
dev->device_handle = open(path, O_RDWR | O_CLOEXEC);
if (dev->device_handle < 0 && errno == EACCES) {
/* udev might be setting up permissions, wait a bit and try again */
usleep(1 * 1000);
continue;
}
break;
}
/* If we have a good handle, return it. */
if (dev->device_handle >= 0) {

View file

@ -21,6 +21,8 @@
********************************************************/
#include "../../SDL_internal.h"
#include "SDL_hints.h"
/* See Apple Technical Note TN2187 for details on IOHidManager. */
#include <IOKit/hid/IOHIDManager.h>
@ -156,11 +158,12 @@ static hid_device *new_hid_device(void)
static void free_hid_device(hid_device *dev)
{
struct input_report *rpt;
if (!dev)
return;
/* Delete any input reports still left over. */
struct input_report *rpt = dev->input_reports;
rpt = dev->input_reports;
while (rpt) {
struct input_report *next = rpt->next;
free(rpt->data);
@ -260,14 +263,12 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
buf[0] = 0;
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
len --;
CFIndex str_len = CFStringGetLength(str);
CFIndex used_buf_len, chars_copied;
CFRange range;
CFIndex str_len = CFStringGetLength(str);
len --;
range.location = 0;
range.length = (str_len > len)? len: str_len;
CFIndex used_buf_len;
CFIndex chars_copied;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF32LE,
@ -299,14 +300,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
buf[0] = 0;
if (str && CFGetTypeID(str) == CFStringGetTypeID()) {
len--;
CFIndex str_len = CFStringGetLength(str);
CFIndex used_buf_len, chars_copied;
CFRange range;
CFIndex str_len = CFStringGetLength(str);
len--;
range.location = 0;
range.length = (str_len > len)? len: str_len;
CFIndex used_buf_len;
CFIndex chars_copied;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF8,
@ -517,7 +516,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
struct hid_device_info *root = NULL; // return object
struct hid_device_info *cur_dev = NULL;
CFIndex num_devices;
CFSetRef device_set;
IOHIDDeviceRef *device_array;
int i;
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
/* Set up the HID Manager if it hasn't been done */
if (hid_init() < 0)
@ -527,7 +529,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
process_pending_events();
/* Get a list of the Devices */
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
device_set = IOHIDManagerCopyDevices(hid_mgr);
if (!device_set)
return NULL;
@ -537,7 +539,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
CFRelease(device_set);
return NULL;
}
IOHIDDeviceRef *device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
device_array = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef));
CFSetGetValues(device_set, (const void **) device_array);
/* Iterate over each device, making an entry for it. */
@ -568,9 +570,19 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
dev_vid = get_vendor_id(dev);
dev_pid = get_product_id(dev);
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", dev_vid);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", dev_vid, dev_pid);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
continue;
}
}
/* Check the VID/PID against the arguments */
if ((vendor_id == 0x0 && product_id == 0x0) ||
(vendor_id == dev_vid && product_id == dev_pid)) {
if ((vendor_id == 0x0 || dev_vid == vendor_id) &&
(product_id == 0x0 || dev_pid == product_id)) {
struct hid_device_info *tmp;
/* VID/PID match. Create the record. */
@ -733,13 +745,14 @@ static void perform_signal_callback(void *context)
static void *read_thread(void *param)
{
hid_device *dev = (hid_device *)param;
CFRunLoopSourceContext ctx;
SInt32 code;
/* Move the device's run loop to this thread. */
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
/* Create the RunLoopSource which is used to signal the
event loop to stop when hid_close() is called. */
CFRunLoopSourceContext ctx;
memset(&ctx, 0, sizeof(ctx));
ctx.version = 0;
ctx.info = dev;
@ -756,11 +769,10 @@ static void *read_thread(void *param)
/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
reports into the hid_report_callback(). */
SInt32 code;
while (!dev->shutdown_thread && !dev->disconnected) {
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
/* Return if the device has been disconnected */
if (code == kCFRunLoopRunFinished) {
if (code == kCFRunLoopRunFinished || code == kCFRunLoopRunStopped) {
dev->disconnected = 1;
break;
}
@ -796,23 +808,29 @@ static void *read_thread(void *param)
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
{
int i;
int i;
hid_device *dev = NULL;
CFIndex num_devices;
CFSetRef device_set;
IOHIDDeviceRef *device_array;
dev = new_hid_device();
/* Set up the HID Manager if it hasn't been done */
if (hid_init() < 0)
return NULL;
#if 0 /* We have a path because the IOHIDManager is already updated */
/* give the IOHIDManager a chance to update itself */
process_pending_events();
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
#endif
device_set = IOHIDManagerCopyDevices(hid_mgr);
if (!device_set)
return NULL;
num_devices = CFSetGetCount(device_set);
IOHIDDeviceRef *device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
device_array = (IOHIDDeviceRef *)calloc(num_devices, sizeof(IOHIDDeviceRef));
CFSetGetValues(device_set, (const void **) device_array);
for (i = 0; i < num_devices; i++) {
char cbuf[BUF_LEN];
@ -824,6 +842,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
if (ret == kIOReturnSuccess) {
char str[32];
struct hid_device_list_node *node;
free(device_array);
CFRelease(device_set);
@ -836,7 +855,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
/* Create the Run Loop Mode for this device.
printing the reference seems to work. */
sprintf(str, "HIDAPI_%p", os_dev);
snprintf(str, sizeof(str), "HIDAPI_%p", os_dev);
dev->run_loop_mode =
CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
@ -845,7 +864,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
os_dev, dev->input_report_buf, dev->max_input_report_len,
&hid_report_callback, dev);
struct hid_device_list_node *node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
node->dev = dev;
node->next = device_list;
device_list = node;
@ -1083,13 +1102,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
{
CFIndex len = length;
IOReturn res;
int skipped_report_id = 0, report_number;
/* Return if the device has been unplugged. */
if (dev->disconnected)
return -1;
int skipped_report_id = 0;
int report_number = data[0];
report_number = data[0];
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
will remain in byte 0. */

View file

@ -21,6 +21,8 @@
********************************************************/
#include "../../SDL_internal.h"
#include "SDL_hints.h"
#include <windows.h>
#ifndef _WIN32_WINNT_WIN8
@ -344,13 +346,14 @@ int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
{ 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard */
{ 0x045E, 0x0822 }, /* Microsoft Precision Mouse */
{ 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset */
{ 0x1CCF, 0x0000 }, /* All Konami Amusement Devices */
/* Turns into an Android controller when enumerated... */
{ 0x0738, 0x2217 } /* SPEEDLINK COMPETITION PRO */
};
for (i = 0; i < (sizeof(known_bad)/sizeof(known_bad[0])); i++) {
if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid)) {
if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid || known_bad[i].pid == 0x0000)) {
return 1;
}
}
@ -371,6 +374,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
int device_index = 0;
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
if (hid_init() < 0)
return NULL;
@ -488,6 +492,16 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
HidD_GetAttributes(write_handle, &attrib);
//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
/* See if there are any devices we should skip in enumeration */
if (hint) {
char vendor_match[16], product_match[16];
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", attrib.VendorID);
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", attrib.VendorID, attrib.ProductID);
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
continue;
}
}
/* Check the VID/PID to see if we should add this
device to the enumeration list. */
if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&