Merge pull request #12015 from nyanpasu64/gc-adapter-sleep-detach

Fix GC Adapter breaking and burning a full CPU core after sleep-wake on Linux
This commit is contained in:
Admiral H. Curtiss 2023-07-22 03:38:45 +02:00 committed by GitHub
commit fb2b3753b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 13 deletions

View File

@ -198,12 +198,11 @@ void GamecubeControllersWidget::SaveSettings()
static_cast<s32>(i)); static_cast<s32>(i));
} }
} }
}
if (GCAdapter::UseAdapter()) if (GCAdapter::UseAdapter())
GCAdapter::StartScanThread(); GCAdapter::StartScanThread();
else else
GCAdapter::StopScanThread(); GCAdapter::StopScanThread();
}
SConfig::GetInstance().SaveSettings(); SConfig::GetInstance().SaveSettings();
} }

View File

@ -203,14 +203,25 @@ static void ReadThreadFunc()
std::array<u8, CONTROLER_INPUT_PAYLOAD_EXPECTED_SIZE> input_buffer; std::array<u8, CONTROLER_INPUT_PAYLOAD_EXPECTED_SIZE> input_buffer;
int payload_size = 0; int payload_size = 0;
const int error = int error = libusb_interrupt_transfer(s_handle, s_endpoint_in, input_buffer.data(),
libusb_interrupt_transfer(s_handle, s_endpoint_in, input_buffer.data(),
int(input_buffer.size()), &payload_size, USB_TIMEOUT_MS); int(input_buffer.size()), &payload_size, USB_TIMEOUT_MS);
if (error != LIBUSB_SUCCESS) if (error != LIBUSB_SUCCESS)
{ {
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Read: libusb_interrupt_transfer failed: {}", ERROR_LOG_FMT(CONTROLLERINTERFACE, "Read: libusb_interrupt_transfer failed: {}",
LibusbUtils::ErrorWrap(error)); LibusbUtils::ErrorWrap(error));
} }
if (error == LIBUSB_ERROR_IO)
{
// s_read_adapter_thread_running is cleared by the joiner, not the stopper.
// Reset the device, which may trigger a replug.
error = libusb_reset_device(s_handle);
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Read: libusb_reset_device: {}",
LibusbUtils::ErrorWrap(error));
// If error is nonzero, try fixing it next loop iteration. We can't easily return
// and cleanup program state without getting another thread to call Reset().
}
ProcessInputPayload(input_buffer.data(), payload_size); ProcessInputPayload(input_buffer.data(), payload_size);
@ -614,8 +625,8 @@ static bool CheckDeviceAccess(libusb_device* device)
static void AddGCAdapter(libusb_device* device) static void AddGCAdapter(libusb_device* device)
{ {
libusb_config_descriptor* config = nullptr; auto [error, config] = LibusbUtils::MakeConfigDescriptor(device);
if (const int error = libusb_get_config_descriptor(device, 0, &config); error != LIBUSB_SUCCESS) if (error != LIBUSB_SUCCESS)
{ {
WARN_LOG_FMT(CONTROLLERINTERFACE, "libusb_get_config_descriptor failed: {}", WARN_LOG_FMT(CONTROLLERINTERFACE, "libusb_get_config_descriptor failed: {}",
LibusbUtils::ErrorWrap(error)); LibusbUtils::ErrorWrap(error));
@ -636,11 +647,11 @@ static void AddGCAdapter(libusb_device* device)
} }
} }
} }
config.reset();
int size = 0; int size = 0;
std::array<u8, CONTROLER_OUTPUT_INIT_PAYLOAD_SIZE> payload = {0x13}; std::array<u8, CONTROLER_OUTPUT_INIT_PAYLOAD_SIZE> payload = {0x13};
const int error = error = libusb_interrupt_transfer(s_handle, s_endpoint_out, payload.data(),
libusb_interrupt_transfer(s_handle, s_endpoint_out, payload.data(),
CONTROLER_OUTPUT_INIT_PAYLOAD_SIZE, &size, USB_TIMEOUT_MS); CONTROLER_OUTPUT_INIT_PAYLOAD_SIZE, &size, USB_TIMEOUT_MS);
if (error != LIBUSB_SUCCESS) if (error != LIBUSB_SUCCESS)
{ {