From ebd5ba380db86f92ae341c2103e4c4f31ee80a3f Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 26 Jan 2022 13:44:14 -0500 Subject: [PATCH] USB Kit: Use libtextencoding to perform character set conversions. This way USB devices with actual Unicode names will not be mangled. Change-Id: I59b50d38776f185cbdb4df9763608341c059a163 --- src/kits/device/Jamfile | 2 +- src/kits/device/USBDevice.cpp | 37 +++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/kits/device/Jamfile b/src/kits/device/Jamfile index 59faa82210..bae5eff090 100644 --- a/src/kits/device/Jamfile +++ b/src/kits/device/Jamfile @@ -20,7 +20,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { USBEndpoint.cpp USBInterface.cpp USBRoster.cpp - : be [ TargetLibsupc++ ] + : be textencoding [ TargetLibsupc++ ] ; } } diff --git a/src/kits/device/USBDevice.cpp b/src/kits/device/USBDevice.cpp index 130baa1b2e..553a96aee9 100644 --- a/src/kits/device/USBDevice.cpp +++ b/src/kits/device/USBDevice.cpp @@ -6,8 +6,10 @@ * Michael Lotz */ +#include #include #include +#include #include #include #include @@ -269,21 +271,40 @@ BUSBDevice::DecodeStringDescriptor(uint32 index) const usb_string_descriptor *stringDescriptor; stringDescriptor = (usb_string_descriptor *)&buffer; - size_t stringLength = GetStringDescriptor(index, stringDescriptor, - sizeof(buffer) - sizeof(usb_string_descriptor)); + int32 stringLength = GetStringDescriptor(index, stringDescriptor, + sizeof(buffer) - sizeof(usb_string_descriptor)) - 1; if (stringLength < 3) return NULL; - // pseudo convert unicode string - stringLength = (stringLength - 2) / 2; - char *result = new(std::nothrow) char[stringLength + 1]; + int32 resultLength = 0; + + // USB is always little-endian, UCS-2 is big-endian. + uint16* ustr = (uint16*)stringDescriptor->string; + for (int32 i = 0; i < (stringLength / 2); i++) { + // Increase size of result as needed by source character. + const uint16 character = B_LENDIAN_TO_HOST_INT16(ustr[i]); + resultLength++; + if (character >= 0x80) + resultLength++; + if (character >= 0x800) + resultLength++; + + ustr[i] = B_SWAP_INT16(ustr[i]); + } + + char *result = new(std::nothrow) char[resultLength + 1]; if (result == NULL) return NULL; - for (size_t i = 0; i < stringLength; i++) - result[i] = stringDescriptor->string[i * 2]; - result[stringLength] = 0; + status_t status = convert_to_utf8(B_UNICODE_CONVERSION, + (const char*)stringDescriptor->string, &stringLength, + result, &resultLength, NULL); + if (status != B_OK) { + delete[] result; + return NULL; + } + result[resultLength] = 0; return result; }