From 43e7723b35a356a071b825da500ffb38a274926b Mon Sep 17 00:00:00 2001 From: deReeperJosh Date: Tue, 21 Nov 2023 15:09:19 +0000 Subject: [PATCH] nsyshid: Fix SetProtocol and SetReport for Libusb Backend --- src/Cafe/OS/libs/nsyshid/BackendLibusb.cpp | 90 +++++++++++++++------- src/Cafe/OS/libs/nsyshid/nsyshid.cpp | 1 - 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/Cafe/OS/libs/nsyshid/BackendLibusb.cpp b/src/Cafe/OS/libs/nsyshid/BackendLibusb.cpp index 4f88b7ed7..308cc6d49 100644 --- a/src/Cafe/OS/libs/nsyshid/BackendLibusb.cpp +++ b/src/Cafe/OS/libs/nsyshid/BackendLibusb.cpp @@ -694,22 +694,58 @@ namespace nsyshid::backend::libusb return false; } - // ToDo: implement this -#if 0 - // is this correct? Discarding "ifIndex" seems like a bad idea - int ret = libusb_set_configuration(handleLock->getHandle(), protocol); - if (ret == 0) { - cemuLog_logDebug(LogType::Force, - "nsyshid::DeviceLibusb::setProtocol(): success"); - return true; + struct libusb_config_descriptor* conf = nullptr; + libusb_device* dev = libusb_get_device(handleLock->GetHandle()); + int getConfig = libusb_get_active_config_descriptor(dev, &conf); + if (getConfig == LIBUSB_SUCCESS) + { + for (uint8 i = 0; i < conf->bNumInterfaces; ++i) + { + int releaseSuccess = libusb_release_interface(handleLock->GetHandle(), i); + if (releaseSuccess < LIBUSB_SUCCESS) + { + cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): Failed to release interface %i", i); + return false; + } + } + } + else + { + cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): Failed to Get Active Config"); + } + + const int setConfig = libusb_set_configuration(handleLock->GetHandle(), protocol); + if (setConfig == LIBUSB_SUCCESS) + { + getConfig = libusb_get_active_config_descriptor(dev, &conf); + if (getConfig == LIBUSB_SUCCESS) + { + for (uint8 i = 0; i < conf->bNumInterfaces; ++i) + { + int detachSuccess = libusb_detach_kernel_driver(handleLock->GetHandle(), i); + if (detachSuccess < LIBUSB_SUCCESS && detachSuccess != LIBUSB_ERROR_NOT_FOUND && + detachSuccess != LIBUSB_ERROR_NOT_SUPPORTED) + { + cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): failed to detach kernel driver"); + return false; + } + int claimInterface = libusb_claim_interface(handleLock->GetHandle(), i); + if (claimInterface < LIBUSB_SUCCESS) + { + cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): failed to claim interface"); + return false; + } + } + } + + libusb_free_config_descriptor(conf); + } + else + { + cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): Failed to set config %i", protocol); + return false; } - cemuLog_logDebug(LogType::Force, - "nsyshid::DeviceLibusb::setProtocol(): failed with error code: {}", - ret); - return false; -#endif - // pretend that everything is fine return true; } @@ -723,18 +759,20 @@ namespace nsyshid::backend::libusb return false; } - // ToDo: implement this -#if 0 - // not sure if libusb_control_transfer() is the right candidate for this - int ret = libusb_control_transfer(handleLock->getHandle(), - bmRequestType, - bRequest, - wValue, - wIndex, - reportData, - length, - timeout); -#endif + int ret = libusb_control_transfer(handleLock->GetHandle(), + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + LIBUSB_REQUEST_SET_CONFIGURATION, + 512 /* This may be skylander specific, but other games don't use this method anyway */, + 0, + originalData, + originalLength, + 0); + + if (ret != originalLength) + { + cemuLog_log(LogType::Force, "nsyshid::DeviceLibusb::SetReport(): Control Transfer Failed: {}", libusb_error_name(ret)); + return false; + } // pretend that everything is fine return true; diff --git a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp index b21e2a43b..ba3e3b96f 100644 --- a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp +++ b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp @@ -332,7 +332,6 @@ namespace nsyshid { sprintf(debugOutput + i * 3, "%02x ", data[i]); } - fmt::print("{} Data: {}\n", prefix, debugOutput); cemuLog_logDebug(LogType::Force, "[{}] Data: {}", prefix, debugOutput); }