mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Fix issues with the GC adapter handling code
If we successfully detach the kernel driver from the interface, we should continue instead of aborting the setup. And we should not use libusb_handle_events(), as the API says it is only for backwards compatibility. Additionally, if the adapter thread is not active, dolphin will take 60 seconds to close because the libusb_handle_events() timeout is hardcoded to 60 seconds. Instead, use libusb_handle_events_timeout_completed() with a timeout of 1 second. Also, cancel the libusb transfers before the join(), to be able to close the usb device without libusb screaming in the background (and potentially crashing). And finally, split the Init() and Shutdown() functions to avoid having to init and exit libusb every time we neeed to detect the adapter.
This commit is contained in:
parent
a2b872b9da
commit
8e556603af
@ -55,9 +55,10 @@ extern "C"
|
||||
|
||||
static void HandleEvents()
|
||||
{
|
||||
timeval tv = {1, 0};
|
||||
while (s_adapter_thread_running.IsSet())
|
||||
{
|
||||
libusb_handle_events(NULL);
|
||||
libusb_handle_events_timeout_completed(s_libusb_context, &tv, NULL);
|
||||
Common::YieldCPU();
|
||||
}
|
||||
}
|
||||
@ -92,12 +93,6 @@ void Init()
|
||||
|
||||
s_libusb_driver_not_supported = false;
|
||||
|
||||
for (int i = 0; i < MAX_SI_CHANNELS; i++)
|
||||
{
|
||||
s_controller_type[i] = CONTROLLER_NONE;
|
||||
s_controller_rumble[i] = 0;
|
||||
}
|
||||
|
||||
int ret = libusb_init(&s_libusb_context);
|
||||
|
||||
if (ret)
|
||||
@ -107,8 +102,23 @@ void Init()
|
||||
}
|
||||
else
|
||||
{
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
|
||||
void Setup()
|
||||
{
|
||||
int ret;
|
||||
libusb_device** list;
|
||||
ssize_t cnt = libusb_get_device_list(nullptr, &list);
|
||||
ssize_t cnt = libusb_get_device_list(s_libusb_context, &list);
|
||||
|
||||
for (int i = 0; i < MAX_SI_CHANNELS; i++)
|
||||
{
|
||||
s_controller_type[i] = CONTROLLER_NONE;
|
||||
s_controller_rumble[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
for (int d = 0; d < cnt; d++)
|
||||
{
|
||||
libusb_device* device = list[d];
|
||||
@ -164,8 +174,12 @@ void Init()
|
||||
ERROR_LOG(SERIALINTERFACE, "libusb_detach_kernel_driver failed with error: %d", ret);
|
||||
Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddGCAdapter(device);
|
||||
}
|
||||
else if (ret != 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED)
|
||||
}
|
||||
else if ((ret != 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
ERROR_LOG(SERIALINTERFACE, "libusb_kernel_driver_active error ret = %d", ret);
|
||||
Shutdown();
|
||||
@ -176,6 +190,17 @@ void Init()
|
||||
Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddGCAdapter(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(list, 1);
|
||||
}
|
||||
|
||||
|
||||
void AddGCAdapter(libusb_device* device)
|
||||
{
|
||||
libusb_config_descriptor *config = nullptr;
|
||||
libusb_get_config_descriptor(device, 0, &config);
|
||||
@ -185,7 +210,7 @@ void Init()
|
||||
for (int i = 0; i < interfaceContainer->num_altsetting; i++)
|
||||
{
|
||||
const libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i];
|
||||
for (int e = 0; e < (int)interface->bNumEndpoints; e++)
|
||||
for (u8 e = 0; e < interface->bNumEndpoints; e++)
|
||||
{
|
||||
const libusb_endpoint_descriptor *endpoint = &interface->endpoint[e];
|
||||
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN)
|
||||
@ -209,7 +234,7 @@ void Init()
|
||||
{
|
||||
s_irq_transfer_read = libusb_alloc_transfer(0);
|
||||
s_irq_transfer_write = libusb_alloc_transfer(0);
|
||||
libusb_fill_interrupt_transfer(s_irq_transfer_read, s_handle, s_endpoint_in, s_controller_payload_swap, sizeof(s_controller_payload_swap), read_callback, NULL, 16);
|
||||
libusb_fill_interrupt_transfer(s_irq_transfer_read, s_handle, s_endpoint_in, s_controller_payload_swap, sizeof(s_controller_payload_swap), read_callback, NULL, 0);
|
||||
libusb_submit_transfer(s_irq_transfer_read);
|
||||
|
||||
s_adapter_thread_running.Set(true);
|
||||
@ -218,18 +243,35 @@ void Init()
|
||||
|
||||
s_detected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(list, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
|
||||
Reset();
|
||||
|
||||
if (s_libusb_context)
|
||||
{
|
||||
libusb_exit(s_libusb_context);
|
||||
s_libusb_context = nullptr;
|
||||
}
|
||||
|
||||
s_libusb_driver_not_supported = false;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (!SConfig::GetInstance().m_GameCubeAdapter)
|
||||
return;
|
||||
|
||||
if (!SConfig::GetInstance().m_GameCubeAdapterThread)
|
||||
{
|
||||
|
||||
if (s_irq_transfer_read)
|
||||
libusb_cancel_transfer(s_irq_transfer_read);
|
||||
if (s_irq_transfer_write)
|
||||
libusb_cancel_transfer(s_irq_transfer_write);
|
||||
}
|
||||
|
||||
if (s_adapter_thread_running.TestAndClear())
|
||||
{
|
||||
s_adapter_thread.join();
|
||||
@ -251,15 +293,8 @@ void Shutdown()
|
||||
|
||||
for (int i = 0; i < MAX_SI_CHANNELS; i++)
|
||||
s_controller_type[i] = CONTROLLER_NONE;
|
||||
|
||||
if (s_libusb_context)
|
||||
{
|
||||
libusb_exit(s_libusb_context);
|
||||
s_libusb_context = nullptr;
|
||||
}
|
||||
|
||||
s_libusb_driver_not_supported = false;
|
||||
}
|
||||
|
||||
void Input(int chan, GCPadStatus* pad)
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
struct libusb_device;
|
||||
|
||||
#include "Common/Thread.h"
|
||||
#include "Core/HW/SI.h"
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
@ -12,7 +14,10 @@ namespace SI_GCAdapter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Reset();
|
||||
void Setup();
|
||||
void Shutdown();
|
||||
void AddGCAdapter(libusb_device* device);
|
||||
void Input(int chan, GCPadStatus* pad);
|
||||
void Output(int chan, u8 rumble_command);
|
||||
bool IsDetected();
|
||||
|
Loading…
x
Reference in New Issue
Block a user