From 4e682461cc6668c860405560446ae33de3490f27 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 17 Jan 2020 10:43:14 -0800 Subject: [PATCH] Reattach the kernel driver after closing USB controllers --- src/hidapi/SDL_hidapi.c | 3 +++ src/hidapi/libusb/hid.c | 14 ++++++++++++++ src/joystick/hidapi/SDL_hidapijoystick.c | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index 1e54e3063..1cf3e1bc9 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -165,6 +165,7 @@ static struct int (*release_interface)(libusb_device_handle *dev_handle, int interface_number); int (*kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number); int (*detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number); + int (*attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number); int (*set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting); struct libusb_transfer * (*alloc_transfer)(int iso_packets); int (*submit_transfer)(struct libusb_transfer *transfer); @@ -208,6 +209,7 @@ static struct #define libusb_release_interface libusb_ctx.release_interface #define libusb_kernel_driver_active libusb_ctx.kernel_driver_active #define libusb_detach_kernel_driver libusb_ctx.detach_kernel_driver +#define libusb_attach_kernel_driver libusb_ctx.attach_kernel_driver #define libusb_set_interface_alt_setting libusb_ctx.set_interface_alt_setting #define libusb_alloc_transfer libusb_ctx.alloc_transfer #define libusb_submit_transfer libusb_ctx.submit_transfer @@ -474,6 +476,7 @@ int HID_API_EXPORT HID_API_CALL hid_init(void) LOAD_LIBUSB_SYMBOL(release_interface) LOAD_LIBUSB_SYMBOL(kernel_driver_active) LOAD_LIBUSB_SYMBOL(detach_kernel_driver) + LOAD_LIBUSB_SYMBOL(attach_kernel_driver) LOAD_LIBUSB_SYMBOL(set_interface_alt_setting) LOAD_LIBUSB_SYMBOL(alloc_transfer) LOAD_LIBUSB_SYMBOL(submit_transfer) diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index d6dfaf38f..967c86f73 100644 --- a/src/hidapi/libusb/hid.c +++ b/src/hidapi/libusb/hid.c @@ -141,6 +141,7 @@ struct hid_device_ { /* The interface number of the HID */ int interface; + int detached_driver; /* Indexes of Strings */ int manufacturer_index; @@ -983,6 +984,8 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) if (should_enumerate_interface(desc.idVendor, intf_desc)) { char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); if (!strcmp(dev_path, path)) { + int detached_driver = 0; + /* Matched Paths. Open this device */ /* OPEN HERE */ @@ -1006,6 +1009,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) good_open = 0; break; } + detached_driver = 1; } #endif @@ -1030,6 +1034,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive) /* Store off the interface number */ dev->interface = intf_desc->bInterfaceNumber; + dev->detached_driver = detached_driver; /* Find the INPUT and OUTPUT endpoints. An OUTPUT endpoint is not required. */ @@ -1335,6 +1340,15 @@ void HID_API_EXPORT hid_close(hid_device *dev) /* release the interface */ libusb_release_interface(dev->device_handle, dev->interface); +#ifdef DETACH_KERNEL_DRIVER + /* Re-attach kernel driver if necessary. */ + if (dev->detached_driver) { + int res = libusb_attach_kernel_driver(dev->device_handle, dev->interface); + if (res < 0) + LOG("Couldn't re-attach kernel driver.\n"); + } +#endif + /* Close the handle */ libusb_close(dev->device_handle); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 768dc74c7..2ae57e687 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -844,6 +844,14 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons } SDL_UnlockJoysticks(); + /* If we're looking for the wireless XBox 360 controller, also look for the dongle */ + if (!result && vendor_id == 0x045e && product_id == 0x02a1) { + return HIDAPI_IsDevicePresent(0x045e, 0x0719, version, name); + } + +#ifdef DEBUG_HIDAPI + SDL_Log("HIDAPI_IsDevicePresent() returning %s for 0x%.4x / 0x%.4x\n", result ? "true" : "false", vendor_id, product_id); +#endif return result; }