Currently, we are using u16string_view which is problematic because the endianness of this type isn't LE but native. We need it to be LE for USB to understand it correctly. This may mean that we need our own fixed sized string container that automatically converts string (constants or otherwise) into LE bytes.
template<std::size_t N>
struct usb_string {
std::array<char16_t, N> data;
consteval usb_string(char16_t const (&p_str)[N]) {
for (std::size_t i = 0; i < N; ++i) {
if constexpr (std::endian::native == std::endian::little) {
data[i] = p_str[i];
} else {
// Byte-swap to LE
data[i] = (p_str[i] >> 8) | (p_str[i] << 8);
}
}
}
constexpr std::span<char16_t const> view() const {
return std::span(data).first(N - 1); // exclude null terminator
}
constexpr operator std::span<char16_t const>() const {
return view();
}
};
Something like the above:
static constexpr auto manufacturer = usb_string(u"ACME Corp");
// In descriptor:
.p_manufacturer = manufacturer.view(),
Currently, we are using
u16string_viewwhich is problematic because the endianness of this type isn't LE but native. We need it to be LE for USB to understand it correctly. This may mean that we need our own fixed sized string container that automatically converts string (constants or otherwise) into LE bytes.Something like the above: