Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
IvanSanchez opened this issue Jan 30, 2018 · 3 comments
Closed

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

IvanSanchez opened this issue Jan 30, 2018 · 3 comments
Labels
bug feature-request Feature or Enhancement windows

Comments

@IvanSanchez
Copy link
Contributor

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.

@reconbot
Copy link
Member

reconbot commented Feb 3, 2018

This is great research, I learned something about how windows handles these devices.

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?

This is the question. The code responsible can be found here and we go a step further parsing it a little more in JS here to have a consistent output. Even if you're not familiar with c++ windows keeps consistent names between their api calls in different languages. So you can google the function names (eg SetupDiGetClassDevs) to get more info.

Figuring out the answer to your question is the first step to improving this feature. =)

@reconbot reconbot added windows feature-request Feature or Enhancement bug labels Feb 3, 2018
@IvanSanchez
Copy link
Contributor Author

One of my colleagues has been playing around with making more lookups to the win32 registry; it should be possible to iterate through the USB device tree looking for matching serial numbers, and see if the "device" is a USB interface or the USB device as a whole.

If our research is successful, we should have a PR ready in like a week or so. 🤞

@IvanSanchez
Copy link
Contributor Author

IvanSanchez commented Feb 15, 2018

Progress! Some of our code can already iterate through the registry keys, and match the container ID of the device nodes for the ports.

image

The code is ugly, the algorithm is clunky, I have no f***ing clue how to compare a char* to a WCHAR*, but hey, it's looking good.

IvanSanchez pushed a commit to NordicPlayground/node-serialport that referenced this issue Feb 28, 2018
…rialport#1483)

Serial numbers in win32 from USB devices cannot be readily derived from the PnP ID.
This adds some logic to iterate through the win32 registry, as per the research in serialport#1459.
reconbot pushed a commit that referenced this issue Feb 28, 2018
)

Serial numbers in win32 from USB devices cannot be readily derived from the PnP ID.
This adds some logic to iterate through the win32 registry, as per the research in #1459.
oteku pushed a commit to Cutii/node-serialport that referenced this issue Apr 9, 2018
…rialport#1483)

Serial numbers in win32 from USB devices cannot be readily derived from the PnP ID.
This adds some logic to iterate through the win32 registry, as per the research in serialport#1459.
@lock lock bot locked as resolved and limited conversation to collaborators Aug 27, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug feature-request Feature or Enhancement windows
Development

No branches or pull requests

2 participants