Merge pull request #1984 from mathieui/GCAdapter-fixes

Fix issues with the GC adapter handling code
This commit is contained in:
skidau
2015-02-12 09:54:53 +11:00
2 changed files with 150 additions and 110 deletions

View File

@ -55,9 +55,10 @@ extern "C"
static void HandleEvents() static void HandleEvents()
{ {
timeval tv = {1, 0};
while (s_adapter_thread_running.IsSet()) while (s_adapter_thread_running.IsSet())
{ {
libusb_handle_events(NULL); libusb_handle_events_timeout_completed(s_libusb_context, &tv, NULL);
Common::YieldCPU(); Common::YieldCPU();
} }
} }
@ -92,12 +93,6 @@ void Init()
s_libusb_driver_not_supported = false; 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); int ret = libusb_init(&s_libusb_context);
if (ret) if (ret)
@ -107,8 +102,23 @@ void Init()
} }
else else
{ {
Setup();
}
}
void Setup()
{
int ret;
libusb_device** list; 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++) for (int d = 0; d < cnt; d++)
{ {
libusb_device* device = list[d]; libusb_device* device = list[d];
@ -164,8 +174,12 @@ void Init()
ERROR_LOG(SERIALINTERFACE, "libusb_detach_kernel_driver failed with error: %d", ret); ERROR_LOG(SERIALINTERFACE, "libusb_detach_kernel_driver failed with error: %d", ret);
Shutdown(); 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); ERROR_LOG(SERIALINTERFACE, "libusb_kernel_driver_active error ret = %d", ret);
Shutdown(); Shutdown();
@ -176,6 +190,17 @@ void Init()
Shutdown(); Shutdown();
} }
else else
{
AddGCAdapter(device);
}
}
}
libusb_free_device_list(list, 1);
}
void AddGCAdapter(libusb_device* device)
{ {
libusb_config_descriptor *config = nullptr; libusb_config_descriptor *config = nullptr;
libusb_get_config_descriptor(device, 0, &config); libusb_get_config_descriptor(device, 0, &config);
@ -185,7 +210,7 @@ void Init()
for (int i = 0; i < interfaceContainer->num_altsetting; i++) for (int i = 0; i < interfaceContainer->num_altsetting; i++)
{ {
const libusb_interface_descriptor *interface = &interfaceContainer->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]; const libusb_endpoint_descriptor *endpoint = &interface->endpoint[e];
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN)
@ -209,7 +234,7 @@ void Init()
{ {
s_irq_transfer_read = libusb_alloc_transfer(0); s_irq_transfer_read = libusb_alloc_transfer(0);
s_irq_transfer_write = 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); libusb_submit_transfer(s_irq_transfer_read);
s_adapter_thread_running.Set(true); s_adapter_thread_running.Set(true);
@ -218,18 +243,35 @@ void Init()
s_detected = true; s_detected = true;
} }
}
}
libusb_free_device_list(list, 1);
}
}
void Shutdown() 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) if (!SConfig::GetInstance().m_GameCubeAdapter)
return; 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()) if (s_adapter_thread_running.TestAndClear())
{ {
s_adapter_thread.join(); s_adapter_thread.join();
@ -251,15 +293,8 @@ void Shutdown()
for (int i = 0; i < MAX_SI_CHANNELS; i++) for (int i = 0; i < MAX_SI_CHANNELS; i++)
s_controller_type[i] = CONTROLLER_NONE; 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) void Input(int chan, GCPadStatus* pad)
{ {

View File

@ -4,6 +4,8 @@
#pragma once #pragma once
struct libusb_device;
#include "Common/Thread.h" #include "Common/Thread.h"
#include "Core/HW/SI.h" #include "Core/HW/SI.h"
#include "InputCommon/GCPadStatus.h" #include "InputCommon/GCPadStatus.h"
@ -12,7 +14,10 @@ namespace SI_GCAdapter
{ {
void Init(); void Init();
void Reset();
void Setup();
void Shutdown(); void Shutdown();
void AddGCAdapter(libusb_device* device);
void Input(int chan, GCPadStatus* pad); void Input(int chan, GCPadStatus* pad);
void Output(int chan, u8 rumble_command); void Output(int chan, u8 rumble_command);
bool IsDetected(); bool IsDetected();