-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Windows: Get proper string description of usb serial port via DeviceIoControl. #725
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
base: master
Are you sure you want to change the base?
Conversation
|
I was exited to try this code, but unfortunately I did not have success with it on Windows 11 for listing the properties of BBC micro:bit v2. With unmodified Pyserial I got: but after applying your patch I got even less information: The value of the Product field I am looking for, is "BBC micro:bit CMSIS-DAP" and usbview.exe does report it like this. |
|
I also tested it on Windows 10 and got the same result. I'm attaching my usbview report from Windows 11, in case you'd like to investigate, why I didn't get the expected result. |
By the way, are you using the latest commit ( Since the earliest commit I forgot about the composite device. the latest commit should fix these issues. |
Yes, I was using https://github.com/pyserial/pyserial/blob/c090f45667c68b7a7259a38de7a59b49b016f851/serial/tools/list_ports_windows.py and https://github.com/pyserial/pyserial/blob/c090f45667c68b7a7259a38de7a59b49b016f851/serial/win32.py for patching my Pyserial. I'll see later, whether the patched version works with my other devices. |
|
I now tested your patch with more devices (SAMD-s from Adafruit, Rasperry Pi Pico, several ESP32-S2 and S3 devices, some plain ESP32 devices with CP and CH UART adapters, an ESP8266 with CP2104 UART adapter, a NRF52 device) and found out that with most of these it worked nicely. The few, that showed proper Product (and Manufacturer) in usbview.exe, but not with your patch, were:
Please let me know, if you need usbview report for any of these! |
I read the USBView report you provided for the BBC micro:bit v2. It looks like my patch misidentifies the composite device as a noncomposite device. This will result in an error similar to the one below. Reads the string description as a composite device: Reads the string description as a noncomposite device: Could you provide me with reports from the USB Device Tree Viewer for these devices? It could provide me with more information to solve the problem. Thanks a lot. |
|
Here come the reports from USB Device Tree Viewer: |
|
Thanks a lot! After your last commit, pyserial reports proper Product, Manufacturer and Serial number for my BBC micro:bit. I'll test with my other boards tomorrow. Great job! |
|
With all my boards I now get proper values for Manufacurer, Product and Serial number. For getting proper Interface, I'm combining your solution with #571. Thank you! |
I refactored the code and added comments to enhance readability. Thank you for your testing, I think this patch is ready to be merged now. |
…oControl. Based on pyserial#725 by @chinaheyu Co-Authored-By: 交叉坐标的星辰 <59406481+chinaheyu@users.noreply.github.com>
I noticed that you want to merge with #571. I've added the feature to read the interface (via I put the old code for getting usb info into |
Don't need pyserial#571 anymore, as pyserial#725 takes care of interface as well.
That's great! Somehow I missed it. I tested it and it works beautifully. I don't need #571 anymore. |
|
It is now possible to get the correct interface field on most devices. |
|
Unfortunately does not seem to work well on devices with multiple serial interfaces, like FT4232H that has 4 UARTs. Unpatched result: Patched result: Location is the same for all COM Ports, e.g. So there is no way to distinguish between the COM ports by location. For linux this seems to have been solved in PR #141 Here's an example of szHardwareID_str: FTDIBUS\VID_0403+PID_6011+6&1AD5555C&0&1&1\0000 |
Since the FTDI driver hides the location information, we had to do some dirty work to get the interface number. I referenced libusbp to parse the hardware id to get the interface number. But apparently it doesn't work. Could you provide me with reports from the USB Device Tree Viewer for your devices? |
ab3ced2 to
c3ffa2c
Compare
|
After the last change most of my devices seem to work same as before, but I get following exception with 3 of my ESP32-C3 devices: Here is the UsbTreeview report for one of them: SeeedXiaoESP32C3.txt The weird thing is that I get this exception only sometimes, usually the first time I call |
|
@chinaheyu, after latest changes I don't get these errors anymore, but I now discovered that with any of these problematic ESP32-C3 devices plugged in, I now occasionally get long delays before It looks like there are two methods, which may cause the delay:
The first call of either method gets stuck in The problem is present also in your older commits, e.g. aivarannamaa@bdab39f#diff-f9966444f1fafc17f351672a463bdcff7833ad6c14a68d9432329a458d1608b0 The next call to Unfortunately I can't create a simple script for reproducing this. The earlier I call Can you recommend some tweaks I could try to learn more about this problem? |
|
Adding to my last comment -- the |
|
@aivarannamaa Thank you very much for your feedback. This is a very peculiar issue that I haven't encountered before. Overall, the problem should be related to the device (ESP32-32 C3) as it seems not to respond with its string description promptly. Subsequent requests are fast because DeviceIoControl caches the result. After receiving your feedback, I purchased a Seeed Xiao ESP32 C3 board, which should arrive today. I will do my best to resolve this peculiar issue. Additionally, I used the same API as in USBView, so did you encounter this issue when using USBView? |
|
@waterfallwhitebread Thank you for providing the screenshot. The latest patch should be able to correctly retrieve the location field of the FT4232H chip. |
This fixes Zadig-bound devices pre Windows 10 Refs pyserial/pyserial#725
|
Is there any update on this? This functionality (corrected device naming on windows) is actually addressed in a couple of the pending PRs, but does not seem to ever get completed. It would be great if one of these could reach completion as this functionality would be very helpful for a number of different of implementations. |
|
I have a report of failure with empty port name (keirf/greaseweazle#549) with the following fix: keirf/greaseweazle#550 Could you please consider this fix, or equivalent, for this upstream PR? |
It seems that some serial devices are not assigned a COMx-style port name. I'm not sure what's causing this, but simply skipping these devices can prevent the program from crashing. In theory, even without a port name, we can still open these serial devices via their interface path, which might serve as an alternative when the port name is None (possibly a better solution than just skipping them). That said, keirf/greaseweazle#550 is correct and necessary. Many thanks for the fix. |
This fixes empty name fields in the Windows serial port list. Fixes #549 Refs pyserial/pyserial#725
|
Hello, Thanks. |
|
Hello, This also solved my issue on Windows 11 and interface field, with a USB composite (2 CDC ACM) device. Thank you. |
|
Hi, There is an issue in serial number. Without patch: Linux With patch: Notice the serial number junk. Thanks, |
|
Hey, @alonbl, During decoding, we did not use decoding APIs like # Convert wstring to python str.
# Very few devices will have an extra null at the end of string, strip it.
return ctypes.wstring_at(description.contents.bString, description.contents.bLength // 2 - 1).rstrip('\0')Therefore, we are curious whether the device returned an incorrect bLength. Could you download usbtreeview and show me the serial number in the string description section? It should look something like this: Thanks. |
|
Hi @lukehugh, This is interesting! I get the following: Update: I found the hex dump... and now I can see that the host indeed does not receive correct size, I will investigate, thank you for your help! Thanks, |
|
Hi @lukehugh , When using Linux and libusb, I get: I do not understand why in windows we get 0x82 which is the buffer size and in Linux we get 0x24 which is the string size. Maybe there usbview is not showing the correct values? Thanks, |
|
@alonbl Although I can't do anything about what your device returns on Windows. Theoretically, if the string contains extra NULL characters, we should strip them (and indeed, the code does this). Perhaps your Windows PC uses some special code page that doesn't interpret NULL as '\0', so I explicitly used UTF-16LE encoding in the latest commit (00961ac). This might help you. |
|
Hi @lukehugh, |
|
hello, Jaroslav |
|
Regarding whether this PR will be merged, I’d like to give a unified response here. This patch originated from one of my personal side projects. At the time, I was struggling to reliably obtain the correct product string (since registering a USB VID is expensive, we wanted to differentiate devices via the product string instead). Later, I discovered USBView and learned how to retrieve proper USB descriptors using Considering that other users in the pyserial community might have similar needs—and hoping this approach could benefit from broader validation—we decided to submit this PR. With the help of several enthusiastic contributors, it gradually evolved. That said, I am not a pyserial maintainer, so I am not in a position to decide whether this PR should ultimately be merged. Unfortunately, around that time pyserial also appeared to be unmaintained. As a result, I chose to make the patch as self-contained as possible, so users could simply copy the file into their own projects as a workaround. In fact, the code in Today, I’m happy to see that pyserial is active again and gradually receiving new commits. However, I remain uncertain about the future of this PR. From my perspective, the original problem has already been solved; for the community, integrating this patch into other projects is relatively straightforward; but for pyserial itself, merging this PR could introduce breaking changes. In any case, I would very much appreciate hearing from the maintainers. @dpgeorge, @kurtmckee. Thanks everyone for the attention and discussion. |
|
Hi @lukehugh, thanks for the ping. I'm also not a pyserial maintainer. I've been holding off on reviewing this PR for only one reason: I'm waiting for #838 to merge. #838 introduces a command to generate a "test asset", which is a JSON file that aims to contain all of the available information for a given device (or devices, if needed) on a given system. That's useful both for debugging detection issues (like what @alonbl reported with trailing null characters) as well as for mocking system calls to confirm that pyserial is handling the devices properly. #838 introduces such files for sysfs-based operating systems (like Linux), but I've intended to expand the command to support Windows once the PR merges, so that I could ask @alonbl and yourself to please generate the test assets for the devices you're working with. With those test asset files in-hand, as well as files from my own devices on Windows, I've intended to build out the Windows side of the test suite. The Windows code in pyserial is completely untested, and your PR is a significant contribution that inherits that complete lack of testing. I've therefore been waiting to dive into a review of the PR until I can build out some level of device mocking and testing to better understand the before-and-after behavior of your PR. I hope this explanation is helpful for understanding why I haven't reviewed the PR yet. |
|
Hello @kurtmckee , There is always a question of CI and hardware tests.... Do we gain value from simulating hardware for synthetic tests or we invest large amount of resources and eventually we do not test the real-world scenarios. In case of sysfs, it is quite simple as the sysfs abstraction is plain files, so you could commit the relevant sysfs as-is, and only have a In case of windows, it is more difficult, as Windows APIs are much more complex. However, these are static, and decent manual tests of the low-level parts should be sufficient. For sure, having CI or not should not block us from reviewing code... Regards, |
You are correct. I look forward to seeing your review of the code in this PR! |
This pull request helps to get serial port information in windows consistent with other platforms (including description, hwid, serial_number, location, manufacturer, product and interface).
Since the original code didn't get the product string and the manufacturer string was often wrong (inconsistent with Linux and MacOS results), I rewrote all the code in
list_ports_windows.pyto request the usb device descriptor viaDeviceIoControlto get the correct string.Unpatched result:
Patched result:
Linux result:
This code gets the same product string, manufacturer string and serial number as in usbview.
Caution: This patch almost completely rewrites the
list_ports_windows.pyfile, and merging it with any other patch that also includeslist_ports_windows.pywill likely result in unpredictable conflicts.This patch shares the same goal as the following PR — to obtain USB descriptors consistent with those on other platforms:
This patch offers a more comprehensive solution to these related issues:
-hyphen. #771We have tested and verified this patch on the following chips:
This patch has no external dependencies. Before it is merged, you can copy the
serial/tools/list_ports_windows.pyfile from this patch and importcomportsfrom it as a quick workaround.