mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
LibusbUtils: Add GetStringDescriptor function to return unicode strings and replace our libusb_get_string_descriptor_ascii calls.
This commit is contained in:
@ -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<char*>(manufacturer),
|
||||
reinterpret_cast<char*>(product), reinterpret_cast<char*>(serial_number));
|
||||
device_descriptor.bcdDevice, manufacturer, product, serial_number);
|
||||
m_is_wii_bt_module =
|
||||
device_descriptor.idVendor == 0x57e && device_descriptor.idProduct == 0x305;
|
||||
return false;
|
||||
|
@ -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<char*>(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())
|
||||
|
@ -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<std::string> 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<unsigned char*>(&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<unsigned char*>(&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
|
||||
|
@ -4,8 +4,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#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<std::string> GetStringDescriptor(libusb_device_handle* dev_handle,
|
||||
uint8_t desc_index);
|
||||
|
||||
} // namespace LibusbUtils
|
||||
|
||||
template <>
|
||||
|
Reference in New Issue
Block a user