Skip to content

Wrong serial number on CDC ACM composite devices on win32 #1459

Closed
@IvanSanchez

Description

@IvanSanchez

This is kind of a follow-up of #1220.

I'm using serialport v6.0.4 (latest available as of 2018-01-28) on nodejs 8.9. I have a Linux (debian sid) box, and a win32 (Windows 10 v1607 build 14393.2007) box.

The serial port device I'm working with is a nRF52840 preview development kit, loaded with firmware implementing USB CDC ACM for serialport-like communications. It's basically a beefed-up arduino-like board with wireless stuff and its own fully-configurable USB stack.

Summary of Problem

In my case, the serial number of the USB device is set up when compiling the firmware, and is used by the USB stack to populate the iSerial field of the USB descriptor. This is how the serial number looks over the wire (wireshark screenshot):

screenshot_20180129_142425

And this is how a lsusb -v looks like in my linux box (relevant part):

Device Descriptor:                                                                                                                                                                                                                                             
  idVendor           0x1915 Nordic Semiconductor ASA                                                                                                                                                                                                                          
  idProduct          0x521f                                                                                                                                                                                                                                                   
  bcdDevice            1.00                                                                                                                                                                                                                                                   
  iManufacturer           1 Nordic Semiconductor                                                                                                                                                                                                                              
  iProduct                2 nRF52 USB CDC Demo                                                                                                                                                                                                                                
  iSerial                 3 bf8f64cd7b5be46c             

And this is how node-serialport/bin/list.js -f jsonline looks like in linux (with extra line breaks for reading pleasure):

{
"manufacturer":"Nordic Semiconductor",
"serialNumber":"bf8f64cd7b5be46c",
"pnpId":"usb-Nordic_Semiconductor_nRF52_USB_CDC_Demo_bf8f64cd7b5be46c-if00",
"vendorId":"1915",
"productId":"521f",
"comName":"/dev/ttyACM0"
}

So in Linux, I get to see the serial number of the USB device as the serial number. This is good. This is expected.

Now I switch to win32.

The output of node-serialport/bin/list.js -f jsonline in win32 looks like:

{
"comName":"COM5",
"manufacturer":"Microsoft",
"serialNumber":"7&307B223F&1&0000",
"pnpId":"USB\\VID_1915&PID_521F&MI_00\\7&307B223F&1&0000",
"locationId":"0000.0014.0000.005.002.000.000.000.000",
"vendorId":"1915",
"productId":"521F"}

Win32 reports the serial number as 7&307B223F&1&0000, but it should be bf8f64cd7b5be46c... so where does that come from?

The answer is in how win32 handles composite USB devices. If I open up win's device manager, it looks like:

image

If I fire up regedit.exe to see details of those two devices (under HKEY_LOCAL_MACHINE/System/CurrentControlSet/Enum/USB, I can see...

image

Well, that makes sense. One of the devices maps to the USB device as a whole, and the other maps to the CDC ACM interface. And the naming makes sense according to https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/enumeration-of-interfaces-not-grouped-in-collections .

Digging a bit deeper, I can see how the drivers are bound to "devices":

image

So my guess is that serialport is interacting with the usbser.sys kernel driver, fetching information from it - but the right serial number is not available at that level.

The question is: How can serialport check if a serial port is part of a USB composite device, and if so how can it fetch the parent's serial number?

Steps and Code to Reproduce the Issue

Get a hold of a USB composite device with a CDC ACM interface, play around with it with the windows device manager as shown above :-)


Addendum: It is possible to force win32 to bind the usbser.sys to the USB device as a whole: run Zadig, show all devices, choose the composite device, replace usbccgp.sys with usbser.sys (AKA USB Serial (CDC))". In this case, things will look like:

image

...and serialport will be able to fetch the right serial number. However, this prevents other interfaces in the device from working (e.g. a device with CDC ACM and mass storage at the same time), and requires manual user intervention with scary messages, so it's just a stopgap measure.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions