diff --git a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp index 2264d4d956..5fdf8fab06 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp @@ -107,50 +107,15 @@ LibUSBBluetoothAdapter::LibUSBBluetoothAdapter() if (IsBluetoothDevice(device_descriptor) && OpenDevice(device_descriptor, device)) { - unsigned char manufacturer[50] = {}, product[50] = {}, serial_number[50] = {}; - const int manufacturer_ret = libusb_get_string_descriptor_ascii( - m_handle, device_descriptor.iManufacturer, manufacturer, sizeof(manufacturer)); - if (manufacturer_ret < LIBUSB_SUCCESS) - { - WARN_LOG_FMT(IOS_WIIMOTE, - "Failed to get string for manufacturer descriptor {:02x} for device " - "{:04x}:{:04x} (rev {:x}): {}", - device_descriptor.iManufacturer, device_descriptor.idVendor, - device_descriptor.idProduct, device_descriptor.bcdDevice, - LibusbUtils::ErrorWrap(manufacturer_ret)); - manufacturer[0] = '?'; - manufacturer[1] = '\0'; - } - const int product_ret = libusb_get_string_descriptor_ascii( - m_handle, device_descriptor.iProduct, product, sizeof(product)); - if (product_ret < LIBUSB_SUCCESS) - { - WARN_LOG_FMT(IOS_WIIMOTE, - "Failed to get string for product descriptor {:02x} for device " - "{:04x}:{:04x} (rev {:x}): {}", - device_descriptor.iProduct, device_descriptor.idVendor, - device_descriptor.idProduct, device_descriptor.bcdDevice, - LibusbUtils::ErrorWrap(product_ret)); - product[0] = '?'; - product[1] = '\0'; - } - const int serial_ret = libusb_get_string_descriptor_ascii( - m_handle, device_descriptor.iSerialNumber, serial_number, sizeof(serial_number)); - if (serial_ret < LIBUSB_SUCCESS) - { - WARN_LOG_FMT(IOS_WIIMOTE, - "Failed to get string for serial number descriptor {:02x} for device " - "{:04x}:{:04x} (rev {:x}): {}", - device_descriptor.iSerialNumber, device_descriptor.idVendor, - device_descriptor.idProduct, device_descriptor.bcdDevice, - LibusbUtils::ErrorWrap(serial_ret)); - serial_number[0] = '?'; - serial_number[1] = '\0'; - } + const auto manufacturer = + LibusbUtils::GetStringDescriptor(m_handle, device_descriptor.iManufacturer).value_or("?"); + const auto product = + LibusbUtils::GetStringDescriptor(m_handle, device_descriptor.iProduct).value_or("?"); + const auto serial_number = + LibusbUtils::GetStringDescriptor(m_handle, device_descriptor.iSerialNumber).value_or("?"); NOTICE_LOG_FMT(IOS_WIIMOTE, "Using device {:04x}:{:04x} (rev {:x}) for Bluetooth: {} {} {}", device_descriptor.idVendor, device_descriptor.idProduct, - device_descriptor.bcdDevice, reinterpret_cast(manufacturer), - reinterpret_cast(product), reinterpret_cast(serial_number)); + device_descriptor.bcdDevice, manufacturer, product, serial_number); m_is_wii_bt_module = device_descriptor.idVendor == 0x57e && device_descriptor.idProduct == 0x305; return false; diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index 5182b1642c..d14a76b0cc 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -114,27 +114,23 @@ std::string USBHost::GetDeviceNameFromVIDPID(u16 vid, u16 pid) return device_name; context.GetDeviceList([&device_name, vid, pid](libusb_device* device) { - libusb_device_descriptor desc; - + libusb_device_descriptor desc{}; if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) return true; - if (desc.idVendor == vid && desc.idProduct == pid) - { - libusb_device_handle* handle; - if (libusb_open(device, &handle) == LIBUSB_SUCCESS) - { - unsigned char buffer[256]; - if (desc.iProduct && - libusb_get_string_descriptor_ascii(handle, desc.iProduct, buffer, sizeof(buffer)) > 0) - { - device_name = reinterpret_cast(buffer); - } - libusb_close(handle); - } + if (desc.idVendor != vid || desc.idProduct != pid) + return true; + + if (desc.iProduct == 0) return false; - } - return true; + + libusb_device_handle* handle{}; + if (libusb_open(device, &handle) != LIBUSB_SUCCESS) + return false; + + device_name = LibusbUtils::GetStringDescriptor(handle, desc.iProduct).value_or(""); + libusb_close(handle); + return false; }); if (!device_name.empty()) diff --git a/Source/Core/Core/LibusbUtils.cpp b/Source/Core/Core/LibusbUtils.cpp index 1b1852dddd..ba3d0fd8e6 100644 --- a/Source/Core/Core/LibusbUtils.cpp +++ b/Source/Core/Core/LibusbUtils.cpp @@ -12,6 +12,7 @@ #include "Common/Assert.h" #include "Common/Flag.h" +#include "Common/StringUtil.h" #include "Common/Thread.h" namespace LibusbUtils @@ -145,4 +146,54 @@ const char* ErrorWrap::GetStrError() const return "__LIBUSB__ not defined"; #endif } + +std::optional GetStringDescriptor(libusb_device_handle* dev_handle, uint8_t desc_index) +{ +#if defined(__LIBUSB__) + struct StringDescriptor + { + u8 length; + u8 descriptor_type; + char16_t data[127]; + }; + + StringDescriptor buffer{}; + + // Reading lang ID 0 returns a list of lang IDs. + const auto lang_id_result = libusb_get_string_descriptor( + dev_handle, desc_index, 0, reinterpret_cast(&buffer), 4); + + if (lang_id_result != 4 || buffer.length < 4 || buffer.descriptor_type != LIBUSB_DT_STRING) + { + ERROR_LOG_FMT(IOS_USB, "libusb_get_string_descriptor(desc_index={}, lang_id=0) result:{}", + int(desc_index), lang_id_result); + return std::nullopt; + } + + const u16 lang_id = buffer.data[0]; + + const auto str_result = libusb_get_string_descriptor( + dev_handle, desc_index, lang_id, reinterpret_cast(&buffer), 255); + + if (str_result < 2 || buffer.length > str_result || buffer.descriptor_type != LIBUSB_DT_STRING) + { + ERROR_LOG_FMT(IOS_USB, "libusb_get_string_descriptor(desc_index={}, lang_id={}) result:{}", + int(desc_index), lang_id, str_result); + return std::nullopt; + } + + // The UTF-16 data size should be even and equal to the return value. + if ((buffer.length & 1u) != 0 || buffer.length != str_result) + { + WARN_LOG_FMT(IOS_USB, "GetStringDescriptor: buffer.length:{} result:{}", buffer.length, + str_result); + } + + const std::size_t str_length = std::max(0, buffer.length - 2) / 2; + return UTF16ToUTF8(std::u16string_view{buffer.data, str_length}); +#else + return "__LIBUSB__ not defined"; +#endif +} + } // namespace LibusbUtils diff --git a/Source/Core/Core/LibusbUtils.h b/Source/Core/Core/LibusbUtils.h index 89fba398dd..6b73070409 100644 --- a/Source/Core/Core/LibusbUtils.h +++ b/Source/Core/Core/LibusbUtils.h @@ -4,8 +4,10 @@ #pragma once #include + #include #include +#include #include #include "Common/CommonTypes.h" @@ -13,6 +15,7 @@ struct libusb_config_descriptor; struct libusb_context; struct libusb_device; +struct libusb_device_handle; namespace LibusbUtils { @@ -53,6 +56,11 @@ struct ErrorWrap const char* GetStrError() const; const char* GetName() const; }; + +// Returns the UTF-16 descriptor converted to UTF-8 or returns nullopt on error. +std::optional GetStringDescriptor(libusb_device_handle* dev_handle, + uint8_t desc_index); + } // namespace LibusbUtils template <>