Skip to content

cli: let devices refine the product name via getMetadata() - #575

Merged
Sapd merged 2 commits into
Sapd:masterfrom
mschoenlaub:cli-metadata
Sep 10, 2026
Merged

cli: let devices refine the product name via getMetadata()#575
Sapd merged 2 commits into
Sapd:masterfrom
mschoenlaub:cli-metadata

Conversation

@mschoenlaub

Copy link
Copy Markdown
Contributor

Changes made

For Dongles which don't create sub-devices for their paired headsets the HID metadata can give more information about the the headset model.

Checklist

  • I adjusted the README (if needed)
  • For new features in HeadsetControl: I discussed it beforehand in Issues or Discussions and adhered to the wiki

Manuel Schönlaub and others added 2 commits September 8, 2026 16:12
getMetadata() existed in the device API but was never called from the
CLI, so a device that knows more than the USB strings (for example
which headset is currently paired to a generic dongle) could not show
it. Ask the device once, on the handle already opened for the first
feature request; no extra device opens, and the default implementation
returns the same HID strings, so other devices are unaffected.
…locale

refineProductName() widened the device-supplied name with
std::wstring(s.begin(), s.end()). That is wrong in two ways: char is signed on
most platforms, so a byte above 0x7F sign-extends into a negative wchar_t, and
a multi-byte UTF-8 sequence becomes one wide character per byte rather than one
per character. It happens to survive on macOS because wcstombs() masks the value
back on the way out, but on Windows the same bytes come out as mojibake and on
glibc they hit the '?' fallback.

Decoding it properly is not enough on its own: the value is converted straight
back with wstring_to_string(), which goes through wcstombs() and so can only
represent what the current locale encodes. Nothing calls setlocale(), so in the
default C locale every non-ASCII character became '?'.

DeviceMetadata and the HID descriptor strings are defined to be UTF-8, so this
adds an explicit, locale-independent pair for them - string_to_wstring() and
wstring_to_utf8() - and uses it wherever those strings are converted. The pair
is an exact inverse, verified in C, en_US.UTF-8 and de_DE.UTF-8. Surrogate pairs
are handled for the 16-bit wchar_t on Windows, and malformed input becomes
U+FFFD rather than discarding the rest of the name.

hid_error() keeps using wstring_to_string(): those really are platform strings
in the local encoding, not UTF-8.

This also fixes non-ASCII manufacturer and product strings read from the HID
descriptor, which were already being mangled before any of this.
@Sapd
Sapd merged commit ca98ed4 into Sapd:master Sep 10, 2026
6 checks passed
@Sapd Sapd mentioned this pull request Sep 10, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants