1

I have an USBhub (D-Link DUB-H7) connected to my laptop with Windows 10. Connected to the hub are 4 identical PEAK dongles to talk to a CANbus. Now, my problem is to programmatically identify these 4 seperate dongles and knowing which one is which. The dongles are fixed in the hub.

To start I downloaded and installed USBDeview to view my devices. In the program I can see my 4 PCAN-USB dongles and I can see that their Instance ID are different. That's good, now I have my identifier. However, once I try to get the ID's with Python things aren't looking good. This is my following test program:

import win32com.client


wmi = win32com.client.GetObject("winmgmts:")

input("Connect the hub")

dongle_list = [(usb.name, usb.DeviceID) for usb in wmi.InstancesOf("Win32_USBHub")]

input("Disconnect the hub")

nod_list = [(usb.name, usb.DeviceID) for usb in wmi.InstancesOf("Win32_USBHub")]

diff = list(set(dongle_list) - set(nod_list))
for d in diff:
    print(d)

Running this gives me only 2 new usb devices and the ID's point to the USBhub rather than the dongles connected to the hub. I also tried with wmi.InstancesOf("CIM_USBDevice") but the result stays the same.

('Generic USB Hub', 'USB\\VID_05E3&PID_0608\\5&4A43CD6&0&4') 
('Generic USB Hub', 'USB\\VID_05E3&PID_0608\\6&9EBFB9C&0&4')

So how can I retrieve the usb information of the devices connected to the USBhub using Python or powershell/cmd invoked by Python?

Another route I was thinking I could take is by using port identifiers. If I disconnect a dongle I can see that it was connected to Port_#0001.Hub_#000x, where is x is a positive integer. So maybe I could poll the port to see if the dongle is connected and then I too know which one is which (dongles are fixed in the hub). Although I think that using the Instance ID is more foolproof.

Swedgin
  • 815
  • 1
  • 11
  • 20
  • I don't think you've got the WMI enumeration right. I'm not an expert but it looks as if you are looking explicitly for USB hubs so that is all you get. You need to enumerate all USB devices and then filter for the correct device-type I think. – Tonny Nov 15 '19 at 09:11
  • @Tonny Could you tell me what the correct enumeration is? Tried also with `CIM_USBDevice` – Swedgin Nov 15 '19 at 09:13
  • As I said.. I'm not an expert on WMI. Never had any reason to delve into it so I don't know how to do it. I think your question would be better suited to sister site StackOverflow. Most programmers hang out there and not so much on SuperUser. I can flag your question to be moved to StackOverflow if you want. – Tonny Nov 15 '19 at 09:25
  • @Tonny thanks, I wasn't sure where to post this. – Swedgin Nov 15 '19 at 09:27
  • Actually Mobukai initiated the migration before I could do anything. Thank him :-) – Tonny Nov 15 '19 at 09:30

1 Answers1

0

I ended up creating a powershell command and invoke that using Python. I noticed however that the InstanceID's are hardware addresses of the the USBhub and not the dongles. I also noticed that the dongles sometimes switch their addresses related on how they were connected. So I also needed to disable them and enable them again in the order I want.

This is what I have now:

poll_cmd = """
$ret = (Get-PnpDevice | ? {($_.description -like "*pcan*") -and ($_.status -eq "ok")} | sort instanceid).instanceid;
$ret | % {Disable-PnpDevice $_ -Confirm:$False};
$ret | % {Start-Sleep -Seconds 1; Enable-PnpDevice $_ -Confirm:$False};
$ret
"""

usbs = (
    subprocess.check_output(["powershell.exe", poll_cmd])
    .decode()
    .strip()
    .split("\r\n")
)

usbs holds the list of usb dongles I'm interested in.

However this gave me one more problem: UAC. I need admin rights to enable the usbs. And used the top answer from Request UAC elevation from within a Python script? to give my program admin rights.

Swedgin
  • 815
  • 1
  • 11
  • 20