Merge pull request #10729 from Pokechu22/libusb-error-wrap

Improve libusb error logging
This commit is contained in:
Admiral H. Curtiss 2022-06-17 16:01:46 +02:00 committed by GitHub
commit 23ed611077
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 130 additions and 68 deletions

View File

@ -71,7 +71,9 @@ BluetoothRealDevice::~BluetoothRealDevice()
{ {
SendHCIResetCommand(); SendHCIResetCommand();
WaitForHCICommandComplete(HCI_CMD_RESET); WaitForHCICommandComplete(HCI_CMD_RESET);
libusb_release_interface(m_handle, 0); const int ret = libusb_release_interface(m_handle, 0);
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_release_interface failed: {}", LibusbUtils::ErrorWrap(ret));
libusb_close(m_handle); libusb_close(m_handle);
libusb_unref_device(m_device); libusb_unref_device(m_device);
} }
@ -84,14 +86,15 @@ std::optional<IPCReply> BluetoothRealDevice::Open(const OpenRequest& request)
return IPCReply(IPC_EACCES); return IPCReply(IPC_EACCES);
m_last_open_error.clear(); m_last_open_error.clear();
m_context.GetDeviceList([this](libusb_device* device) { const int ret = m_context.GetDeviceList([this](libusb_device* device) {
libusb_device_descriptor device_descriptor; libusb_device_descriptor device_descriptor;
libusb_get_device_descriptor(device, &device_descriptor); libusb_get_device_descriptor(device, &device_descriptor);
auto config_descriptor = LibusbUtils::MakeConfigDescriptor(device); auto [ret, config_descriptor] = LibusbUtils::MakeConfigDescriptor(device);
if (!config_descriptor) if (ret != LIBUSB_SUCCESS || !config_descriptor)
{ {
ERROR_LOG_FMT(IOS_WIIMOTE, "Failed to get config descriptor for device {:04x}:{:04x}", ERROR_LOG_FMT(IOS_WIIMOTE, "Failed to get config descriptor for device {:04x}:{:04x}: {}",
device_descriptor.idVendor, device_descriptor.idProduct); device_descriptor.idVendor, device_descriptor.idProduct,
LibusbUtils::ErrorWrap(ret));
return true; return true;
} }
@ -100,12 +103,22 @@ std::optional<IPCReply> BluetoothRealDevice::Open(const OpenRequest& request)
if (IsBluetoothDevice(descriptor) && IsWantedDevice(device_descriptor) && OpenDevice(device)) if (IsBluetoothDevice(descriptor) && IsWantedDevice(device_descriptor) && OpenDevice(device))
{ {
unsigned char manufacturer[50] = {}, product[50] = {}, serial_number[50] = {}; unsigned char manufacturer[50] = {}, product[50] = {}, serial_number[50] = {};
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iManufacturer, manufacturer, const int manufacturer_ret = libusb_get_string_descriptor_ascii(
sizeof(manufacturer)); m_handle, device_descriptor.iManufacturer, manufacturer, sizeof(manufacturer));
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iProduct, product, const int product_ret = libusb_get_string_descriptor_ascii(
sizeof(product)); m_handle, device_descriptor.iProduct, product, sizeof(product));
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iSerialNumber, serial_number, const int serial_ret = libusb_get_string_descriptor_ascii(
sizeof(serial_number)); m_handle, device_descriptor.iSerialNumber, serial_number, sizeof(serial_number));
if (manufacturer_ret < LIBUSB_SUCCESS || product_ret < LIBUSB_SUCCESS ||
serial_ret < LIBUSB_SUCCESS)
{
ERROR_LOG_FMT(IOS_WIIMOTE,
"Failed to get descriptor for device {:04x}:{:04x} (rev {:x}): {}/{}/{}",
device_descriptor.idVendor, device_descriptor.idProduct,
device_descriptor.bcdDevice, LibusbUtils::ErrorWrap(manufacturer_ret),
LibusbUtils::ErrorWrap(product_ret), LibusbUtils::ErrorWrap(serial_ret));
return true;
}
NOTICE_LOG_FMT(IOS_WIIMOTE, "Using device {:04x}:{:04x} (rev {:x}) for Bluetooth: {} {} {}", NOTICE_LOG_FMT(IOS_WIIMOTE, "Using device {:04x}:{:04x} (rev {:x}) for Bluetooth: {} {} {}",
device_descriptor.idVendor, device_descriptor.idProduct, device_descriptor.idVendor, device_descriptor.idProduct,
device_descriptor.bcdDevice, reinterpret_cast<char*>(manufacturer), device_descriptor.bcdDevice, reinterpret_cast<char*>(manufacturer),
@ -116,6 +129,11 @@ std::optional<IPCReply> BluetoothRealDevice::Open(const OpenRequest& request)
} }
return true; return true;
}); });
if (ret != LIBUSB_SUCCESS)
{
m_last_open_error =
Common::FmtFormatT("GetDeviceList failed: {0}", LibusbUtils::ErrorWrap(ret));
}
if (m_handle == nullptr) if (m_handle == nullptr)
{ {
@ -144,7 +162,9 @@ std::optional<IPCReply> BluetoothRealDevice::Close(u32 fd)
{ {
if (m_handle) if (m_handle)
{ {
libusb_release_interface(m_handle, 0); const int ret = libusb_release_interface(m_handle, 0);
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_release_interface failed: {}", LibusbUtils::ErrorWrap(ret));
libusb_close(m_handle); libusb_close(m_handle);
libusb_unref_device(m_device); libusb_unref_device(m_device);
m_handle = nullptr; m_handle = nullptr;
@ -205,7 +225,9 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
}; };
PendingTransfer pending_transfer{std::move(cmd), std::move(buffer)}; PendingTransfer pending_transfer{std::move(cmd), std::move(buffer)};
m_current_transfers.emplace(transfer, std::move(pending_transfer)); m_current_transfers.emplace(transfer, std::move(pending_transfer));
libusb_submit_transfer(transfer); const int ret = libusb_submit_transfer(transfer);
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_submit_transfer failed: {}", LibusbUtils::ErrorWrap(ret));
break; break;
} }
// ACL data (incoming or outgoing) and incoming HCI events (respectively) // ACL data (incoming or outgoing) and incoming HCI events (respectively)
@ -255,7 +277,9 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
transfer->user_data = this; transfer->user_data = this;
PendingTransfer pending_transfer{std::move(cmd), std::move(buffer)}; PendingTransfer pending_transfer{std::move(cmd), std::move(buffer)};
m_current_transfers.emplace(transfer, std::move(pending_transfer)); m_current_transfers.emplace(transfer, std::move(pending_transfer));
libusb_submit_transfer(transfer); const int ret = libusb_submit_transfer(transfer);
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_submit_transfer failed: {}", LibusbUtils::ErrorWrap(ret));
break; break;
} }
} }
@ -357,7 +381,7 @@ void BluetoothRealDevice::WaitForHCICommandComplete(const u16 opcode)
{ {
const int ret = libusb_interrupt_transfer(m_handle, HCI_EVENT, buffer.data(), const int ret = libusb_interrupt_transfer(m_handle, HCI_EVENT, buffer.data(),
static_cast<int>(buffer.size()), &actual_length, 20); static_cast<int>(buffer.size()), &actual_length, 20);
if (ret != 0 || actual_length < static_cast<int>(sizeof(packet))) if (ret != LIBUSB_SUCCESS || actual_length < static_cast<int>(sizeof(packet)))
continue; continue;
std::memcpy(&packet, buffer.data(), sizeof(packet)); std::memcpy(&packet, buffer.data(), sizeof(packet));
if (packet.EventType == HCI_EVENT_COMMAND_COMPL && packet.Opcode == opcode) if (packet.EventType == HCI_EVENT_COMMAND_COMPL && packet.Opcode == opcode)
@ -370,8 +394,12 @@ void BluetoothRealDevice::SendHCIResetCommand()
u8 packet[3] = {}; u8 packet[3] = {};
const u16 payload[] = {HCI_CMD_RESET}; const u16 payload[] = {HCI_CMD_RESET};
memcpy(packet, payload, sizeof(payload)); memcpy(packet, payload, sizeof(payload));
libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, packet, sizeof(packet), TIMEOUT); const int ret =
INFO_LOG_FMT(IOS_WIIMOTE, "Sent a reset command to adapter"); libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, packet, sizeof(packet), TIMEOUT);
if (ret < LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_control_transfer failed: {}", LibusbUtils::ErrorWrap(ret));
else
INFO_LOG_FMT(IOS_WIIMOTE, "Sent a reset command to adapter");
} }
void BluetoothRealDevice::SendHCIDeleteLinkKeyCommand() void BluetoothRealDevice::SendHCIDeleteLinkKeyCommand()
@ -387,8 +415,11 @@ void BluetoothRealDevice::SendHCIDeleteLinkKeyCommand()
payload.command.bdaddr = {}; payload.command.bdaddr = {};
payload.command.delete_all = true; payload.command.delete_all = true;
libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, reinterpret_cast<u8*>(&payload), const int ret =
static_cast<u16>(sizeof(payload)), TIMEOUT); libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, reinterpret_cast<u8*>(&payload),
static_cast<u16>(sizeof(payload)), TIMEOUT);
if (ret < LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_control_transfer failed: {}", LibusbUtils::ErrorWrap(ret));
} }
bool BluetoothRealDevice::SendHCIStoreLinkKeyCommand() bool BluetoothRealDevice::SendHCIStoreLinkKeyCommand()
@ -425,8 +456,10 @@ bool BluetoothRealDevice::SendHCIStoreLinkKeyCommand()
iterator += entry.second.size(); iterator += entry.second.size();
} }
libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, packet.data(), const int ret = libusb_control_transfer(m_handle, REQUEST_TYPE, 0, 0, 0, packet.data(),
static_cast<u16>(packet.size()), TIMEOUT); static_cast<u16>(packet.size()), TIMEOUT);
if (ret < LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_WIIMOTE, "libusb_control_transfer failed: {}", LibusbUtils::ErrorWrap(ret));
return true; return true;
} }
@ -566,10 +599,10 @@ bool BluetoothRealDevice::OpenDevice(libusb_device* device)
{ {
m_device = libusb_ref_device(device); m_device = libusb_ref_device(device);
const int ret = libusb_open(m_device, &m_handle); const int ret = libusb_open(m_device, &m_handle);
if (ret != 0) if (ret != LIBUSB_SUCCESS)
{ {
m_last_open_error = m_last_open_error =
Common::FmtFormatT("Failed to open Bluetooth device: {0}", libusb_error_name(ret)); Common::FmtFormatT("Failed to open Bluetooth device: {0}", LibusbUtils::ErrorWrap(ret));
return false; return false;
} }
@ -577,20 +610,22 @@ bool BluetoothRealDevice::OpenDevice(libusb_device* device)
// https://lists.freebsd.org/pipermail/freebsd-usb/2016-March/014161.html // https://lists.freebsd.org/pipermail/freebsd-usb/2016-March/014161.html
#ifndef __FreeBSD__ #ifndef __FreeBSD__
int result = libusb_set_auto_detach_kernel_driver(m_handle, 1); int result = libusb_set_auto_detach_kernel_driver(m_handle, 1);
if (result != 0) if (result != LIBUSB_SUCCESS)
{ {
result = libusb_detach_kernel_driver(m_handle, INTERFACE); result = libusb_detach_kernel_driver(m_handle, INTERFACE);
if (result < 0 && result != LIBUSB_ERROR_NOT_FOUND && result != LIBUSB_ERROR_NOT_SUPPORTED) if (result != LIBUSB_SUCCESS && result != LIBUSB_ERROR_NOT_FOUND &&
result != LIBUSB_ERROR_NOT_SUPPORTED)
{ {
m_last_open_error = Common::FmtFormatT( m_last_open_error = Common::FmtFormatT(
"Failed to detach kernel driver for BT passthrough: {0}", libusb_error_name(result)); "Failed to detach kernel driver for BT passthrough: {0}", LibusbUtils::ErrorWrap(result));
return false; return false;
} }
} }
#endif #endif
if (libusb_claim_interface(m_handle, INTERFACE) < 0) if (const int result2 = libusb_claim_interface(m_handle, INTERFACE); result2 != LIBUSB_SUCCESS)
{ {
m_last_open_error = Common::GetStringT("Failed to claim interface for BT passthrough"); m_last_open_error = Common::FmtFormatT("Failed to claim interface for BT passthrough: {0}",
LibusbUtils::ErrorWrap(result2));
return false; return false;
} }

View File

@ -121,7 +121,7 @@ bool USBHost::AddNewDevices(std::set<u64>& new_devices, DeviceChangeHooks& hooks
if (m_context.IsValid()) if (m_context.IsValid())
{ {
m_context.GetDeviceList([&](libusb_device* device) { const int ret = m_context.GetDeviceList([&](libusb_device* device) {
libusb_device_descriptor descriptor; libusb_device_descriptor descriptor;
libusb_get_device_descriptor(device, &descriptor); libusb_get_device_descriptor(device, &descriptor);
if (whitelist.count({descriptor.idVendor, descriptor.idProduct}) == 0) if (whitelist.count({descriptor.idVendor, descriptor.idProduct}) == 0)
@ -137,6 +137,8 @@ bool USBHost::AddNewDevices(std::set<u64>& new_devices, DeviceChangeHooks& hooks
hooks.emplace(GetDeviceById(id), ChangeEvent::Inserted); hooks.emplace(GetDeviceById(id), ChangeEvent::Inserted);
return true; return true;
}); });
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_USB, "GetDeviceList failed: {}", LibusbUtils::ErrorWrap(ret));
} }
#endif #endif
return true; return true;

View File

@ -36,7 +36,15 @@ LibusbDevice::LibusbDevice(Kernel& ios, libusb_device* device,
static_cast<u64>(libusb_get_device_address(device))); static_cast<u64>(libusb_get_device_address(device)));
for (u8 i = 0; i < descriptor.bNumConfigurations; ++i) for (u8 i = 0; i < descriptor.bNumConfigurations; ++i)
m_config_descriptors.emplace_back(LibusbUtils::MakeConfigDescriptor(m_device, i)); {
auto [ret, config_descriptor] = LibusbUtils::MakeConfigDescriptor(m_device, i);
if (ret != LIBUSB_SUCCESS || !config_descriptor)
{
WARN_LOG_FMT(IOS_USB, "Failed to make config descriptor {} for {:04x}:{:04x}: {}", i, m_vid,
m_pid, LibusbUtils::ErrorWrap(ret));
}
m_config_descriptors.emplace_back(std::move(config_descriptor));
}
} }
LibusbDevice::~LibusbDevice() LibusbDevice::~LibusbDevice()
@ -133,15 +141,15 @@ bool LibusbDevice::Attach()
{ {
NOTICE_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Opening device", m_vid, m_pid); NOTICE_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Opening device", m_vid, m_pid);
const int ret = libusb_open(m_device, &m_handle); const int ret = libusb_open(m_device, &m_handle);
if (ret != 0) if (ret != LIBUSB_SUCCESS)
{ {
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to open: {}", m_vid, m_pid, ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to open: {}", m_vid, m_pid,
libusb_error_name(ret)); LibusbUtils::ErrorWrap(ret));
m_handle = nullptr; m_handle = nullptr;
return false; return false;
} }
} }
if (ClaimAllInterfaces(DEFAULT_CONFIG_NUM) < 0) if (ClaimAllInterfaces(DEFAULT_CONFIG_NUM) < LIBUSB_SUCCESS)
return false; return false;
m_device_attached = true; m_device_attached = true;
return true; return true;
@ -153,7 +161,7 @@ bool LibusbDevice::AttachAndChangeInterface(const u8 interface)
return false; return false;
if (interface != m_active_interface) if (interface != m_active_interface)
return ChangeInterface(interface) == 0; return ChangeInterface(interface) == LIBUSB_SUCCESS;
return true; return true;
} }
@ -174,7 +182,7 @@ int LibusbDevice::ChangeInterface(const u8 interface)
INFO_LOG_FMT(IOS_USB, "[{:04x}:{:04x} {}] Changing interface to {}", m_vid, m_pid, INFO_LOG_FMT(IOS_USB, "[{:04x}:{:04x} {}] Changing interface to {}", m_vid, m_pid,
m_active_interface, interface); m_active_interface, interface);
m_active_interface = interface; m_active_interface = interface;
return 0; return LIBUSB_SUCCESS;
} }
int LibusbDevice::SetAltSetting(const u8 alt_setting) int LibusbDevice::SetAltSetting(const u8 alt_setting)
@ -208,15 +216,15 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
if (static_cast<u8>(cmd->index) != m_active_interface) if (static_cast<u8>(cmd->index) != m_active_interface)
{ {
const int ret = ChangeInterface(static_cast<u8>(cmd->index)); const int ret = ChangeInterface(static_cast<u8>(cmd->index));
if (ret < 0) if (ret < LIBUSB_SUCCESS)
{ {
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x} {}] Failed to change interface to {}: {}", m_vid, ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x} {}] Failed to change interface to {}: {}", m_vid,
m_pid, m_active_interface, cmd->index, libusb_error_name(ret)); m_pid, m_active_interface, cmd->index, LibusbUtils::ErrorWrap(ret));
return ret; return ret;
} }
} }
const int ret = SetAltSetting(static_cast<u8>(cmd->value)); const int ret = SetAltSetting(static_cast<u8>(cmd->value));
if (ret == 0) if (ret == LIBUSB_SUCCESS)
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
return ret; return ret;
} }
@ -226,7 +234,7 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
m_vid, m_pid, m_active_interface, cmd->index, cmd->value); m_vid, m_pid, m_active_interface, cmd->index, cmd->value);
ReleaseAllInterfacesForCurrentConfig(); ReleaseAllInterfacesForCurrentConfig();
const int ret = libusb_set_configuration(m_handle, cmd->value); const int ret = libusb_set_configuration(m_handle, cmd->value);
if (ret == 0) if (ret == LIBUSB_SUCCESS)
{ {
ClaimAllInterfaces(cmd->value); ClaimAllInterfaces(cmd->value);
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
@ -368,7 +376,7 @@ void LibusbDevice::TransferEndpoint::HandleTransfer(libusb_transfer* transfer,
const std::unique_ptr<u8[]> buffer(transfer->buffer); const std::unique_ptr<u8[]> buffer(transfer->buffer);
const auto& cmd = *iterator->second.get(); const auto& cmd = *iterator->second.get();
const auto* device = static_cast<LibusbDevice*>(transfer->user_data); const auto* device = static_cast<LibusbDevice*>(transfer->user_data);
s32 return_value = 0; s32 return_value = LIBUSB_SUCCESS;
switch (transfer->status) switch (transfer->status)
{ {
case LIBUSB_TRANSFER_COMPLETED: case LIBUSB_TRANSFER_COMPLETED:
@ -417,7 +425,7 @@ static int DoForEachInterface(const Configs& configs, u8 config_num, Function ac
for (u8 i = 0; i < configs[config_num]->bNumInterfaces; ++i) for (u8 i = 0; i < configs[config_num]->bNumInterfaces; ++i)
{ {
ret = action(i); ret = action(i);
if (ret < 0) if (ret < LIBUSB_SUCCESS)
break; break;
} }
return ret; return ret;
@ -427,15 +435,16 @@ int LibusbDevice::ClaimAllInterfaces(u8 config_num) const
{ {
const int ret = DoForEachInterface(m_config_descriptors, config_num, [this](u8 i) { const int ret = DoForEachInterface(m_config_descriptors, config_num, [this](u8 i) {
const int ret2 = libusb_detach_kernel_driver(m_handle, i); const int ret2 = libusb_detach_kernel_driver(m_handle, i);
if (ret2 < 0 && ret2 != LIBUSB_ERROR_NOT_FOUND && ret2 != LIBUSB_ERROR_NOT_SUPPORTED) if (ret2 < LIBUSB_SUCCESS && ret2 != LIBUSB_ERROR_NOT_FOUND &&
ret2 != LIBUSB_ERROR_NOT_SUPPORTED)
{ {
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to detach kernel driver: {}", m_vid, m_pid, ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to detach kernel driver: {}", m_vid, m_pid,
libusb_error_name(ret2)); LibusbUtils::ErrorWrap(ret2));
return ret2; return ret2;
} }
return libusb_claim_interface(m_handle, i); return libusb_claim_interface(m_handle, i);
}); });
if (ret < 0) if (ret < LIBUSB_SUCCESS)
{ {
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to claim all interfaces (configuration {})", ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to claim all interfaces (configuration {})",
m_vid, m_pid, config_num); m_vid, m_pid, config_num);
@ -448,7 +457,7 @@ int LibusbDevice::ReleaseAllInterfaces(u8 config_num) const
const int ret = DoForEachInterface(m_config_descriptors, config_num, [this](u8 i) { const int ret = DoForEachInterface(m_config_descriptors, config_num, [this](u8 i) {
return libusb_release_interface(m_handle, i); return libusb_release_interface(m_handle, i);
}); });
if (ret < 0 && ret != LIBUSB_ERROR_NO_DEVICE && ret != LIBUSB_ERROR_NOT_FOUND) if (ret < LIBUSB_SUCCESS && ret != LIBUSB_ERROR_NO_DEVICE && ret != LIBUSB_ERROR_NOT_FOUND)
{ {
ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to release all interfaces (configuration {})", ERROR_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Failed to release all interfaces (configuration {})",
m_vid, m_pid, config_num); m_vid, m_pid, config_num);
@ -460,7 +469,7 @@ int LibusbDevice::ReleaseAllInterfacesForCurrentConfig() const
{ {
int config_num; int config_num;
const int get_config_ret = libusb_get_configuration(m_handle, &config_num); const int get_config_ret = libusb_get_configuration(m_handle, &config_num);
if (get_config_ret < 0) if (get_config_ret < LIBUSB_SUCCESS)
return get_config_ret; return get_config_ret;
return ReleaseAllInterfaces(config_num); return ReleaseAllInterfaces(config_num);
} }

View File

@ -28,7 +28,9 @@ public:
return; return;
#ifdef _WIN32 #ifdef _WIN32
libusb_set_option(m_context, LIBUSB_OPTION_USE_USBDK); const int usbdk_ret = libusb_set_option(m_context, LIBUSB_OPTION_USE_USBDK);
if (usbdk_ret != LIBUSB_SUCCESS && usbdk_ret != LIBUSB_ERROR_NOT_FOUND)
WARN_LOG_FMT(IOS_USB, "Failed to set LIBUSB_OPTION_USE_USBDK: {}", ErrorWrap(usbdk_ret));
#endif #endif
m_event_thread_running.Set(); m_event_thread_running.Set();
m_event_thread = std::thread(&Impl::EventThread, this); m_event_thread = std::thread(&Impl::EventThread, this);
@ -45,16 +47,16 @@ public:
libusb_exit(m_context); libusb_exit(m_context);
} }
libusb_context* GetContext() { return m_context; } libusb_context* GetContext() const { return m_context; }
bool GetDeviceList(GetDeviceListCallback callback) int GetDeviceList(GetDeviceListCallback callback) const
{ {
std::lock_guard lock{m_device_list_mutex}; std::lock_guard lock{m_device_list_mutex};
libusb_device** list; libusb_device** list;
ssize_t count = libusb_get_device_list(m_context, &list); ssize_t count = libusb_get_device_list(m_context, &list);
if (count < 0) if (count < 0)
return false; return static_cast<int>(count);
for (ssize_t i = 0; i < count; ++i) for (ssize_t i = 0; i < count; ++i)
{ {
@ -62,7 +64,7 @@ public:
break; break;
} }
libusb_free_device_list(list, 1); libusb_free_device_list(list, 1);
return true; return LIBUSB_SUCCESS;
} }
private: private:
@ -71,11 +73,15 @@ private:
Common::SetCurrentThreadName("libusb thread"); Common::SetCurrentThreadName("libusb thread");
timeval tv{5, 0}; timeval tv{5, 0};
while (m_event_thread_running.IsSet()) while (m_event_thread_running.IsSet())
libusb_handle_events_timeout_completed(m_context, &tv, nullptr); {
const int ret = libusb_handle_events_timeout_completed(m_context, &tv, nullptr);
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(IOS_USB, "libusb_handle_events_timeout_completed failed: {}", ErrorWrap(ret));
}
} }
libusb_context* m_context = nullptr; libusb_context* m_context = nullptr;
std::mutex m_device_list_mutex; mutable std::mutex m_device_list_mutex;
Common::Flag m_event_thread_running; Common::Flag m_event_thread_running;
std::thread m_event_thread; std::thread m_event_thread;
}; };
@ -83,8 +89,8 @@ private:
class Context::Impl class Context::Impl
{ {
public: public:
libusb_context* GetContext() { return nullptr; } libusb_context* GetContext() const { return nullptr; }
bool GetDeviceList(GetDeviceListCallback callback) { return false; } int GetDeviceList(GetDeviceListCallback callback) const { return -1; }
}; };
#endif #endif
@ -104,19 +110,22 @@ bool Context::IsValid() const
return m_impl->GetContext() != nullptr; return m_impl->GetContext() != nullptr;
} }
bool Context::GetDeviceList(GetDeviceListCallback callback) int Context::GetDeviceList(GetDeviceListCallback callback) const
{ {
return m_impl->GetDeviceList(std::move(callback)); return m_impl->GetDeviceList(std::move(callback));
} }
ConfigDescriptor MakeConfigDescriptor(libusb_device* device, u8 config_num) std::pair<int, ConfigDescriptor> MakeConfigDescriptor(libusb_device* device, u8 config_num)
{ {
#if defined(__LIBUSB__) #if defined(__LIBUSB__)
libusb_config_descriptor* descriptor = nullptr; libusb_config_descriptor* descriptor = nullptr;
if (libusb_get_config_descriptor(device, config_num, &descriptor) == LIBUSB_SUCCESS) const int ret = libusb_get_config_descriptor(device, config_num, &descriptor);
return {descriptor, libusb_free_config_descriptor}; if (ret == LIBUSB_SUCCESS)
return {ret, ConfigDescriptor{descriptor, libusb_free_config_descriptor}};
#else
const int ret = -1;
#endif #endif
return {nullptr, [](auto) {}}; return {ret, ConfigDescriptor{nullptr, [](auto) {}}};
} }
const char* ErrorWrap::GetName() const const char* ErrorWrap::GetName() const

View File

@ -6,6 +6,7 @@
#include <fmt/format.h> #include <fmt/format.h>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <utility>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -31,7 +32,7 @@ public:
bool IsValid() const; bool IsValid() const;
// Only valid if the context is valid. // Only valid if the context is valid.
bool GetDeviceList(GetDeviceListCallback callback); int GetDeviceList(GetDeviceListCallback callback) const;
private: private:
class Impl; class Impl;
@ -39,7 +40,7 @@ private:
}; };
using ConfigDescriptor = UniquePtr<libusb_config_descriptor>; using ConfigDescriptor = UniquePtr<libusb_config_descriptor>;
ConfigDescriptor MakeConfigDescriptor(libusb_device* device, u8 config_num = 0); std::pair<int, ConfigDescriptor> MakeConfigDescriptor(libusb_device* device, u8 config_num = 0);
// Wrapper for libusb_error to be used with fmt. Note that we can't create a fmt::formatter // Wrapper for libusb_error to be used with fmt. Note that we can't create a fmt::formatter
// directly for libusb_error as it is a plain enum and most libusb functions actually return an // directly for libusb_error as it is a plain enum and most libusb functions actually return an

View File

@ -71,7 +71,7 @@ enum
ADAPTER_DETECTED = 1, ADAPTER_DETECTED = 1,
}; };
// Current adapter status: detected/not detected/in error (holds the error code) // Current adapter status: detected/not detected/in error (libusb error codes are negative)
static std::atomic<int> s_status = NO_ADAPTER_DETECTED; static std::atomic<int> s_status = NO_ADAPTER_DETECTED;
static libusb_device_handle* s_handle = nullptr; static libusb_device_handle* s_handle = nullptr;
#elif GCADAPTER_USE_ANDROID_IMPLEMENTATION #elif GCADAPTER_USE_ANDROID_IMPLEMENTATION
@ -462,7 +462,7 @@ static void Setup()
s_controller_type.fill(ControllerType::None); s_controller_type.fill(ControllerType::None);
s_controller_rumble.fill(0); s_controller_rumble.fill(0);
s_libusb_context->GetDeviceList([](libusb_device* device) { const int ret = s_libusb_context->GetDeviceList([](libusb_device* device) {
if (CheckDeviceAccess(device)) if (CheckDeviceAccess(device))
{ {
// Only connect to a single adapter in case the user has multiple connected // Only connect to a single adapter in case the user has multiple connected
@ -471,6 +471,8 @@ static void Setup()
} }
return true; return true;
}); });
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(CONTROLLERINTERFACE, "Failed to get device list: {}", LibusbUtils::ErrorWrap(ret));
if (s_status != ADAPTER_DETECTED && prev_status != s_status && s_detect_callback != nullptr) if (s_status != ADAPTER_DETECTED && prev_status != s_status && s_detect_callback != nullptr)
s_detect_callback(); s_detect_callback();
@ -537,7 +539,8 @@ static bool CheckDeviceAccess(libusb_device* device)
// We assume user is using GCAdapterDriver and therefor don't want to detach anything // We assume user is using GCAdapterDriver and therefor don't want to detach anything
#if !defined(__APPLE__) #if !defined(__APPLE__)
ret = libusb_detach_kernel_driver(s_handle, 0); ret = libusb_detach_kernel_driver(s_handle, 0);
detach_failed = ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND && ret != LIBUSB_ERROR_NOT_SUPPORTED; detach_failed =
ret < LIBUSB_SUCCESS && ret != LIBUSB_ERROR_NOT_FOUND && ret != LIBUSB_ERROR_NOT_SUPPORTED;
#endif #endif
if (detach_failed) if (detach_failed)
{ {
@ -555,7 +558,7 @@ static bool CheckDeviceAccess(libusb_device* device)
// This call makes Nyko-brand (and perhaps other) adapters work. // This call makes Nyko-brand (and perhaps other) adapters work.
// However it returns LIBUSB_ERROR_PIPE with Mayflash adapters. // However it returns LIBUSB_ERROR_PIPE with Mayflash adapters.
const int transfer = libusb_control_transfer(s_handle, 0x21, 11, 0x0001, 0, nullptr, 0, 1000); const int transfer = libusb_control_transfer(s_handle, 0x21, 11, 0x0001, 0, nullptr, 0, 1000);
if (transfer < 0) if (transfer < LIBUSB_SUCCESS)
{ {
WARN_LOG_FMT(CONTROLLERINTERFACE, "libusb_control_transfer failed: {}", WARN_LOG_FMT(CONTROLLERINTERFACE, "libusb_control_transfer failed: {}",
LibusbUtils::ErrorWrap(transfer)); LibusbUtils::ErrorWrap(transfer));

View File

@ -11,6 +11,7 @@
#endif #endif
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/LibusbUtils.h" #include "Core/LibusbUtils.h"
// Because opening and getting the device name from devices is slow, especially on Windows // Because opening and getting the device name from devices is slow, especially on Windows
@ -45,13 +46,15 @@ std::map<std::pair<u16, u16>, std::string> GetInsertedDevices()
if (!context.IsValid()) if (!context.IsValid())
return devices; return devices;
context.GetDeviceList([&](libusb_device* device) { const int ret = context.GetDeviceList([&](libusb_device* device) {
libusb_device_descriptor descr; libusb_device_descriptor descr;
libusb_get_device_descriptor(device, &descr); libusb_get_device_descriptor(device, &descr);
const std::pair<u16, u16> vid_pid{descr.idVendor, descr.idProduct}; const std::pair<u16, u16> vid_pid{descr.idVendor, descr.idProduct};
devices[vid_pid] = GetDeviceName(vid_pid); devices[vid_pid] = GetDeviceName(vid_pid);
return true; return true;
}); });
if (ret != LIBUSB_SUCCESS)
WARN_LOG_FMT(COMMON, "GetDeviceList failed: {}", LibusbUtils::ErrorWrap(ret));
#endif #endif
return devices; return devices;