USB String Descriptor, LANGID, and Serial Debugging

Debug USB string descriptors by validating LANGID, manufacturer, product, serial indexes, UTF-16LE length, duplicate identity, retries, bootloader changes, and OS caching.

usb string descriptor, langid, serial number descriptor, manufacturer string, product string, duplicate serial number, usb diagnostics

A USB device can transfer data while still showing a garbled product name, receiving a new COM port, colliding with another unit, or changing identity after a bootloader reset. String descriptors are therefore part of device identity and supportability, not decorative labels. The evidence starts with descriptor indexes, string zero's LANGID list, raw UTF-16LE bytes, and consistency across devices and firmware modes.

Direct answer: capture from connection, inspect the device descriptor's manufacturer, product, and serial indexes, then trace every string GET_DESCRIPTOR request. Validate descriptor type, even byte length, supported LANGID, UTF-16LE payload, and stability across reset. Compare at least two physical units and both application and bootloader identities before blaming OS caching.

Bus Scope can prove which string bytes the host requested and received. It cannot prove how an installer, registry, udev rule, or application later cached or displayed valid identity, so pair bus evidence with host identity logs when raw strings are correct.

String indexes are references, not inline text

The device descriptor contains one-byte indexes:

Field Intended reference
iManufacturer manufacturer string
iProduct product string
iSerialNumber device serial string

A value of zero means no string is provided for that field. A nonzero value promises that the corresponding string descriptor can be requested in a supported language context.

Record both index and response:

Device field Index Request result Decoded value
manufacturer 1 completes Hannes Software
product 2 completes Example Device
serial 3 STALL unavailable despite nonzero index

The last case is inconsistent. Some hosts continue, but identity and UI behavior can vary.

String descriptor zero provides LANGIDs

String index zero is special. Its payload is a list of language identifiers rather than normal text. A typical host sequence can be:

  1. request string index 0;
  2. learn supported LANGID values;
  3. request manufacturer, product, or serial with one of those LANGIDs.

Decode the setup packet:

  • descriptor type and index from wValue;
  • requested LANGID in wIndex for nonzero strings;
  • maximum requested bytes in wLength;
  • returned descriptor length and type.

If string zero lists one language but firmware answers only another, host behavior can differ. Return a coherent list and support the strings actually referenced by the device descriptor.

Validate the raw USB string format

A USB string descriptor contains:

bLength
bDescriptorType = STRING
UTF-16LE code units

The length includes the two header bytes. It should be even for ordinary UTF-16 code-unit data and must not exceed the returned buffer.

Common firmware defects:

  • ASCII bytes returned instead of UTF-16LE;
  • odd bLength;
  • wrong descriptor type;
  • length excludes the two-byte header;
  • buffer contains more text than declared;
  • wLength is ignored and firmware overruns the requested size;
  • a C string terminator is counted as visible content;
  • generated descriptor array is stale.

Inspect raw bytes, not only the decoded label. A tolerant host or decoder can hide an invalid length.

The USB descriptor viewer workflow explains boundary-first validation.

Probe and full-length requests are normal

A host may first request only the descriptor header or a short prefix, then request the complete length. Firmware should return at most the requested bytes and preserve valid control-transfer behavior.

Use a request table:

Request wLength Returned Interpretation
string 2, LANGID 0x0409 2 2 length probe
string 2, LANGID 0x0409 34 34 full product string
string 3, LANGID 0x0409 255 26 valid shorter serial response

Returning fewer bytes than wLength is not automatically truncation. Compare returned bytes with the descriptor's own bLength. A short transfer can correctly terminate the response.

Serial-number stability

A serial descriptor should be stable when the product relies on persistent identity. Test:

  • repeated unplug/replug;
  • bus reset;
  • system reboot;
  • suspend/resume;
  • firmware update;
  • application-to-bootloader transition;
  • two physical devices from the same batch.

Build an identity matrix:

Unit/mode VID:PID bcdDevice Serial Expected
unit A app 1234:1000 0102 A00041 stable
unit A bootloader 1234:1001 0007 A00041 same unit identity
unit B app 1234:1000 0102 A00042 unique

Whether bootloader and application should share a serial is a product decision, but it must be documented. A missing or changing value can force host tools to rediscover the device by port path or another attribute.

Duplicate serial numbers are production defects when uniqueness is promised

Two devices with the same VID, PID, and serial can be treated as one logical identity by host software. Consequences include:

  • wrong COM-port association;
  • provisioning records assigned to the wrong unit;
  • calibration loaded for another device;
  • test logs merged;
  • updater choosing an unintended target;
  • support evidence that cannot distinguish units.

Capture the raw serial response from both physical units. Do not rely only on an OS property page, which can show cached data. Record unit labels and port topology so the comparison is auditable.

If duplicates arise from an uninitialized flash field, firmware should fail manufacturing validation rather than silently publish a default serial.

Missing serial numbers and port-based identity

Some simple products intentionally omit a serial by setting iSerialNumber to zero. That can be valid, but stable per-unit identity may then depend on topology or host policy.

Ask:

  • Must applications distinguish two identical devices?
  • Must a device keep the same COM port after moving ports?
  • Does a firmware updater need to follow one unit through reset?
  • Do deployment rules match on serial?
  • Is licensing or calibration tied to hardware identity?

If stable identity is required, omission is a design issue even when enumeration succeeds.

Manufacturer and product strings

Product-name defects can reveal more than cosmetic text:

  • application and bootloader arrays were mixed;
  • descriptor generation used the wrong build variant;
  • memory corruption changed the response;
  • LANGID routing selected a fallback;
  • string indexes shifted after inserting a new string;
  • host is displaying cached identity from an older descriptor.

Compare raw requests before clearing caches. If current bytes are wrong, fix firmware. If current bytes are correct but the host label is stale, proceed to host cache and device-instance investigation.

Bootloader and application transitions

Firmware updates often involve two identities:

  1. application receives a reset command or control-line transition;
  2. device disconnects;
  3. bootloader enumerates;
  4. update traffic runs;
  5. application returns.

Preserve VID, PID, bcdDevice, manufacturer, product, and serial at each stage. If the serial disappears in bootloader, the updater may need topology-based matching. If several devices are attached, that policy can be unsafe unless explicitly designed.

The USB serial re-enumeration guide covers handle and identity changes.

Composite-device identity

The device-level strings describe the parent. Interfaces can also reference interface strings. Validate:

  • each nonzero interface string index;
  • LANGID support;
  • interface number and alternate setting;
  • whether the host actually requests those strings;
  • consistency with IAD function naming.

Do not use interface strings to repair incorrect class descriptors or grouping. They help humans identify functions but do not replace protocol structure.

Distinguish bus identity from OS cache

Use this boundary:

Evidence Owned by
setup request and returned string bytes USB device/firmware
VID/PID/serial device instance OS enumeration
COM-port assignment OS driver and policy
displayed friendly name driver/installer/UI
application device record application

If the capture shows a changing serial, do not blame cache. If the raw serial is stable but the UI is stale, stop rewriting descriptors and inspect the host layer.

A repeatable string-descriptor workflow

  1. Record firmware, physical unit label, host, port, VID, and PID.
  2. Capture from connection through all string requests.
  3. List device and interface string indexes.
  4. Decode string zero and supported LANGIDs.
  5. Validate setup fields for each nonzero string.
  6. Check raw descriptor type, even length, and UTF-16LE bytes.
  7. Compare probe and full requests.
  8. Repeat after reset, replug, and suspend/resume.
  9. Compare application and bootloader modes.
  10. Compare at least two units for unique serials.
  11. Pair raw identity with OS device-instance logs.
  12. Save bounded .bscope sessions and an identity matrix.

Use Bus Scope platform capture to make sure the correct physical device path is recorded.

QA questions

Must every USB device have a serial number?

No. A zero serial index can be valid. But products that need stable per-unit identity, multiple identical devices, persistent port mapping, provisioning, or safe firmware updates should design and validate one.

Why does the host request string index zero?

String zero returns supported language IDs. The host can use one of them when requesting manufacturer, product, serial, or interface strings.

Are USB strings null-terminated?

The descriptor is length-delimited. Firmware should construct valid UTF-16LE descriptor bytes and bLength; host interpretation should not depend on a C-style terminator.

Why does the product name stay old after firmware fixes it?

First prove the current raw string bytes. If they are correct and stable, the remaining problem can be OS device-instance or friendly-name caching. If bytes are still old, the firmware or generated descriptor remains wrong.

Can Bus Scope prove two devices are physically different?

It can show that two captured sessions returned the same or different identity bytes. Physical labels, manufacturing records, and controlled port mapping are needed to prove which unit produced each capture.

Final diagnosis

USB string debugging is an identity audit: indexes must resolve, LANGIDs must agree, raw UTF-16LE lengths must be valid, and serials must follow the product's uniqueness and persistence policy. Once bus identity is proven, move deliberately to OS caching or application mapping instead of treating every wrong label as the same defect.

What belongs in the identity acceptance table?

Record VID, PID, bcdDevice, string index, requested LANGID, returned length, decoded value, serial persistence after power loss, and the host label after cache refresh. Test at least two physical units when uniqueness matters. A descriptor that decodes correctly but is identical across devices is a product-identity defect, while different bus strings with one stale desktop label point toward host caching. The distinction prevents firmware changes from being used to chase an operating-system record.

<!-- multilingual-related-reading:start -->

Related guides

Continue with the same-language pages below. They cover adjacent stages without changing the canonical owner of this topic:

<!-- multilingual-related-reading:end -->