mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 22:41:18 +12:00
nsyshid: Make Libusb the Windows backend (#1471)
This commit is contained in:
parent
8dd809d725
commit
0a59085021
15 changed files with 412 additions and 773 deletions
|
@ -1,7 +1,5 @@
|
|||
#include "BackendLibusb.h"
|
||||
|
||||
#if NSYSHID_ENABLE_BACKEND_LIBUSB
|
||||
|
||||
namespace nsyshid::backend::libusb
|
||||
{
|
||||
BackendLibusb::BackendLibusb()
|
||||
|
@ -16,7 +14,7 @@ namespace nsyshid::backend::libusb
|
|||
{
|
||||
m_ctx = nullptr;
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::BackendLibusb: failed to initialize libusb, return code: {}",
|
||||
m_initReturnCode);
|
||||
m_initReturnCode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -35,8 +33,8 @@ namespace nsyshid::backend::libusb
|
|||
if (ret != LIBUSB_SUCCESS)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::BackendLibusb: failed to register hotplug callback with return code {}",
|
||||
ret);
|
||||
"nsyshid::BackendLibusb: failed to register hotplug callback with return code {}",
|
||||
ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -53,8 +51,8 @@ namespace nsyshid::backend::libusb
|
|||
if (ret != 0)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::BackendLibusb: hotplug thread: error handling events: {}",
|
||||
ret);
|
||||
"nsyshid::BackendLibusb: hotplug thread: error handling events: {}",
|
||||
ret);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
|
@ -139,8 +137,8 @@ namespace nsyshid::backend::libusb
|
|||
case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::BackendLibusb::OnHotplug(): device arrived: {:04x}:{:04x}",
|
||||
desc.idVendor,
|
||||
desc.idProduct);
|
||||
desc.idVendor,
|
||||
desc.idProduct);
|
||||
auto device = CheckAndCreateDevice(dev);
|
||||
if (device != nullptr)
|
||||
{
|
||||
|
@ -167,8 +165,8 @@ namespace nsyshid::backend::libusb
|
|||
case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::BackendLibusb::OnHotplug(): device left: {:04x}:{:04x}",
|
||||
desc.idVendor,
|
||||
desc.idProduct);
|
||||
desc.idVendor,
|
||||
desc.idProduct);
|
||||
auto device = FindLibusbDevice(dev);
|
||||
if (device != nullptr)
|
||||
{
|
||||
|
@ -204,7 +202,7 @@ namespace nsyshid::backend::libusb
|
|||
if (ret < 0)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::BackendLibusb::FindLibusbDevice(): failed to get device descriptor");
|
||||
"nsyshid::BackendLibusb::FindLibusbDevice(): failed to get device descriptor");
|
||||
return nullptr;
|
||||
}
|
||||
uint8 busNumber = libusb_get_bus_number(dev);
|
||||
|
@ -269,7 +267,7 @@ namespace nsyshid::backend::libusb
|
|||
if (desc.idVendor == 0x0e6f && desc.idProduct == 0x0241)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::BackendLibusb::CheckAndCreateDevice(): lego dimensions portal detected");
|
||||
"nsyshid::BackendLibusb::CheckAndCreateDevice(): lego dimensions portal detected");
|
||||
}
|
||||
auto device = std::make_shared<DeviceLibusb>(m_ctx,
|
||||
desc.idVendor,
|
||||
|
@ -446,12 +444,13 @@ namespace nsyshid::backend::libusb
|
|||
}
|
||||
this->m_handleInUseCounter = 0;
|
||||
}
|
||||
|
||||
int ret = ClaimAllInterfaces(0);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
int ret = ClaimAllInterfaces(0);
|
||||
if (ret != 0)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::open(): cannot claim interface");
|
||||
}
|
||||
cemuLog_log(LogType::Force, "nsyshid::DeviceLibusb::open(): cannot claim interface for config 0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +474,7 @@ namespace nsyshid::backend::libusb
|
|||
{
|
||||
m_handleInUseCounterDecremented.wait(lock);
|
||||
}
|
||||
libusb_release_interface(handle, 0);
|
||||
ReleaseAllInterfacesForCurrentConfig();
|
||||
libusb_close(handle);
|
||||
m_handleInUseCounter = -1;
|
||||
m_handleInUseCounterDecremented.notify_all();
|
||||
|
@ -493,21 +492,26 @@ namespace nsyshid::backend::libusb
|
|||
if (!handleLock->IsValid())
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::DeviceLibusb::read(): cannot read from a non-opened device\n");
|
||||
"nsyshid::DeviceLibusb::read(): cannot read from a non-opened device\n");
|
||||
return ReadResult::Error;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_config_descriptors.size(); i++)
|
||||
{
|
||||
ClaimAllInterfaces(i);
|
||||
}
|
||||
|
||||
const unsigned int timeout = 50;
|
||||
int actualLength = 0;
|
||||
int ret = 0;
|
||||
do
|
||||
{
|
||||
ret = libusb_bulk_transfer(handleLock->GetHandle(),
|
||||
this->m_libusbEndpointIn,
|
||||
message->data,
|
||||
message->length,
|
||||
&actualLength,
|
||||
timeout);
|
||||
ret = libusb_interrupt_transfer(handleLock->GetHandle(),
|
||||
this->m_libusbEndpointIn,
|
||||
message->data,
|
||||
message->length,
|
||||
&actualLength,
|
||||
timeout);
|
||||
}
|
||||
while (ret == LIBUSB_ERROR_TIMEOUT && actualLength == 0 && IsOpened());
|
||||
|
||||
|
@ -521,8 +525,8 @@ namespace nsyshid::backend::libusb
|
|||
return ReadResult::Success;
|
||||
}
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::DeviceLibusb::read(): failed with error code: {}",
|
||||
ret);
|
||||
"nsyshid::DeviceLibusb::read(): failed at endpoint 0x{:02x} with error message: {}", this->m_libusbEndpointIn,
|
||||
libusb_error_name(ret));
|
||||
return ReadResult::Error;
|
||||
}
|
||||
|
||||
|
@ -532,18 +536,23 @@ namespace nsyshid::backend::libusb
|
|||
if (!handleLock->IsValid())
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::DeviceLibusb::write(): cannot write to a non-opened device\n");
|
||||
"nsyshid::DeviceLibusb::write(): cannot write to a non-opened device\n");
|
||||
return WriteResult::Error;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_config_descriptors.size(); i++)
|
||||
{
|
||||
ClaimAllInterfaces(i);
|
||||
}
|
||||
|
||||
message->bytesWritten = 0;
|
||||
int actualLength = 0;
|
||||
int ret = libusb_bulk_transfer(handleLock->GetHandle(),
|
||||
this->m_libusbEndpointOut,
|
||||
message->data,
|
||||
message->length,
|
||||
&actualLength,
|
||||
0);
|
||||
int ret = libusb_interrupt_transfer(handleLock->GetHandle(),
|
||||
this->m_libusbEndpointOut,
|
||||
message->data,
|
||||
message->length,
|
||||
&actualLength,
|
||||
0);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
|
@ -556,14 +565,14 @@ namespace nsyshid::backend::libusb
|
|||
return WriteResult::Success;
|
||||
}
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::DeviceLibusb::write(): failed with error code: {}",
|
||||
ret);
|
||||
"nsyshid::DeviceLibusb::write(): failed with error code: {}",
|
||||
ret);
|
||||
return WriteResult::Error;
|
||||
}
|
||||
|
||||
bool DeviceLibusb::GetDescriptor(uint8 descType,
|
||||
uint8 descIndex,
|
||||
uint8 lang,
|
||||
uint16 lang,
|
||||
uint8* output,
|
||||
uint32 outputMaxLength)
|
||||
{
|
||||
|
@ -579,7 +588,6 @@ namespace nsyshid::backend::libusb
|
|||
struct libusb_config_descriptor* conf = nullptr;
|
||||
libusb_device* dev = libusb_get_device(handleLock->GetHandle());
|
||||
int ret = libusb_get_active_config_descriptor(dev, &conf);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
std::vector<uint8> configurationDescriptor(conf->wTotalLength);
|
||||
|
@ -656,7 +664,6 @@ namespace nsyshid::backend::libusb
|
|||
extraReadPointer += bLength;
|
||||
}
|
||||
}
|
||||
|
||||
for (int endpointIndex = 0; endpointIndex < altsetting.bNumEndpoints; endpointIndex++)
|
||||
{
|
||||
// endpoint descriptor
|
||||
|
@ -681,24 +688,61 @@ namespace nsyshid::backend::libusb
|
|||
uint32 bytesWritten = currentWritePtr - &configurationDescriptor[0];
|
||||
libusb_free_config_descriptor(conf);
|
||||
cemu_assert_debug(bytesWritten <= conf->wTotalLength);
|
||||
|
||||
memcpy(output, &configurationDescriptor[0],
|
||||
std::min<uint32>(outputMaxLength, bytesWritten));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force,
|
||||
"nsyshid::DeviceLibusb::getDescriptor(): failed to get config descriptor with error code: {}",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
uint16 wValue = uint16(descType) << 8 | uint16(descIndex);
|
||||
// HID Get_Descriptor requests are handled via libusb_control_transfer
|
||||
int ret = libusb_control_transfer(handleLock->GetHandle(),
|
||||
LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_ENDPOINT_IN,
|
||||
LIBUSB_REQUEST_GET_DESCRIPTOR,
|
||||
wValue,
|
||||
lang,
|
||||
output,
|
||||
outputMaxLength,
|
||||
0);
|
||||
if (ret != outputMaxLength)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::GetDescriptor(): Control Transfer Failed: {}", libusb_error_name(ret));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceLibusb::SetIdle(uint8 ifIndex,
|
||||
uint8 reportId,
|
||||
uint8 duration)
|
||||
{
|
||||
auto handleLock = AquireHandleLock();
|
||||
if (!handleLock->IsValid())
|
||||
{
|
||||
cemuLog_log(LogType::Force, "nsyshid::DeviceLibusb::SetIdle(): device is not opened");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 wValue = uint16(duration) << 8 | uint16(reportId);
|
||||
|
||||
// HID Set_Idle requests are handled via libusb_control_transfer
|
||||
int ret = libusb_control_transfer(handleLock->GetHandle(),
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||
HID_CLASS_SET_IDLE, // Defined in HID Class Specific Requests (7.2)
|
||||
wValue,
|
||||
ifIndex,
|
||||
nullptr,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetIdle(): Control Transfer Failed: {}", libusb_error_name(ret));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Configs, typename Function>
|
||||
|
@ -767,18 +811,22 @@ namespace nsyshid::backend::libusb
|
|||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): device is not opened");
|
||||
return false;
|
||||
}
|
||||
if (m_interfaceIndex != ifIndex)
|
||||
m_interfaceIndex = ifIndex;
|
||||
|
||||
ReleaseAllInterfacesForCurrentConfig();
|
||||
int ret = libusb_set_configuration(AquireHandleLock()->GetHandle(), protocol);
|
||||
if (ret == LIBUSB_SUCCESS)
|
||||
ret = ClaimAllInterfaces(protocol);
|
||||
int ret = libusb_control_transfer(handleLock->GetHandle(),
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||
HID_CLASS_SET_PROTOCOL, // Defined in HID Class Specific Requests (7.2)
|
||||
protocol,
|
||||
ifIndex,
|
||||
nullptr,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (ret == LIBUSB_SUCCESS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
if (ret != 0)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetProtocol(): Control Transfer Failed: {}", libusb_error_name(ret));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceLibusb::SetReport(ReportMessage* message)
|
||||
|
@ -790,18 +838,20 @@ namespace nsyshid::backend::libusb
|
|||
return false;
|
||||
}
|
||||
|
||||
uint16 wValue = uint16(message->reportType) << 8 | uint16(message->reportId);
|
||||
|
||||
int ret = libusb_control_transfer(handleLock->GetHandle(),
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||
LIBUSB_REQUEST_SET_CONFIGURATION,
|
||||
512,
|
||||
0,
|
||||
message->originalData,
|
||||
message->originalLength,
|
||||
HID_CLASS_SET_REPORT, // Defined in HID Class Specific Requests (7.2)
|
||||
wValue,
|
||||
m_interfaceIndex,
|
||||
message->data,
|
||||
uint16(message->length & 0xFFFF),
|
||||
0);
|
||||
|
||||
if (ret != message->originalLength)
|
||||
if (ret != message->length)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetReport(): Control Transfer Failed: {}", libusb_error_name(ret));
|
||||
cemuLog_logDebug(LogType::Force, "nsyshid::DeviceLibusb::SetReport(): Control Transfer Failed at interface {} : {}", m_interfaceIndex, libusb_error_name(ret));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -854,5 +904,3 @@ namespace nsyshid::backend::libusb
|
|||
return m_handle;
|
||||
}
|
||||
} // namespace nsyshid::backend::libusb
|
||||
|
||||
#endif // NSYSHID_ENABLE_BACKEND_LIBUSB
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue