From 3527b49459ab730a09cb646361ae7528a26a2cf8 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 21 Jan 2021 22:30:34 -0800 Subject: [PATCH] Fixed initializing the Nyko and EVORETRO GameCube adaptors This requires root on most Linux distributions, as we have to directly send USB messages to the devices to enable input reports. --- src/hidapi/SDL_hidapi.c | 51 +++++++++++++++++++++++ src/hidapi/SDL_hidapi.h | 28 +++++++++++++ src/joystick/hidapi/SDL_hidapi_gamecube.c | 3 ++ 3 files changed, 82 insertions(+) create mode 100644 src/hidapi/SDL_hidapi.h diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index d9ad45fda..670a51719 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -955,6 +955,57 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device) return wrapper->backend->hid_error(wrapper->device); } +/* This is needed to enable input for Nyko and EVORETRO GameCube adaptors */ +void SDL_EnableGameCubeAdaptors(void) +{ +#ifdef SDL_LIBUSB_DYNAMIC + libusb_context *usb_context = NULL; + libusb_device **devs = NULL; + libusb_device_handle *handle = NULL; + struct libusb_device_descriptor desc; + ssize_t i, num_devs; + int kernel_detached = 0; + + if (libusb_init(&usb_context) == 0) { + num_devs = libusb_get_device_list(usb_context, &devs); + for (i = 0; i < num_devs; ++i) { + if (libusb_get_device_descriptor(devs[i], &desc) != 0) { + continue; + } + + if (desc.idVendor != 0x057e || desc.idProduct != 0x0337) { + continue; + } + + if (libusb_open(devs[i], &handle) != 0) { + continue; + } + + if (libusb_kernel_driver_active(handle, 0)) { + if (libusb_detach_kernel_driver(handle, 0) == 0) { + kernel_detached = 1; + } + } + + if (libusb_claim_interface(handle, 0) == 0) { + libusb_control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000); + libusb_release_interface(handle, 0); + } + + if (kernel_detached) { + libusb_attach_kernel_driver(handle, 0); + } + + libusb_close(handle); + } + + libusb_free_device_list(devs, 1); + + libusb_exit(usb_context); + } +#endif /* SDL_LIBUSB_DYNAMIC */ +} + #endif /* SDL_JOYSTICK_HIDAPI */ /* vi: set sts=4 ts=4 sw=4 expandtab: */ diff --git a/src/hidapi/SDL_hidapi.h b/src/hidapi/SDL_hidapi.h new file mode 100644 index 000000000..305a00a5c --- /dev/null +++ b/src/hidapi/SDL_hidapi.h @@ -0,0 +1,28 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifdef SDL_JOYSTICK_HIDAPI + +extern void SDL_EnableGameCubeAdaptors(void); + +#endif /* SDL_JOYSTICK_HIDAPI */ + +/* vi: set sts=4 ts=4 sw=4 expandtab: */ diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 6780a0fdd..3f275c84b 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -32,6 +32,7 @@ #include "../SDL_sysjoystick.h" #include "SDL_hidapijoystick_c.h" #include "SDL_hidapi_rumble.h" +#include "../../hidapi/SDL_hidapi.h" #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE @@ -129,6 +130,8 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) Uint8 initMagic = 0x13; Uint8 rumbleMagic = 0x11; + SDL_EnableGameCubeAdaptors(); + ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { SDL_OutOfMemory();