polling_rate.py (2833B)
1 #!/usr/bin/env python3 2 3 import usb 4 5 USB_INTERFACE_CLASS_HID = 0x03 6 7 def usb_device_spec(spec): 8 major = spec >> 8 9 minor = (spec >> 4) & 0xF 10 return f"{major}.{minor}" 11 12 def usb_device_speed(speed): 13 if speed == 1: 14 return "Low-speed" 15 elif speed == 2: 16 return "Full-speed" 17 elif speed == 3: 18 return "High-speed" 19 elif speed == 4: 20 return "SuperSpeed" 21 elif speed == 5: 22 return "SuperSpeed+" 23 24 return "Speed unknown" 25 26 def usb_hid_interface_subclass(subclass): 27 if subclass == 0x00: 28 return "None" 29 elif subclass == 0x01: 30 return "Boot" 31 else: 32 return f"Unknown (0x{subclass:02X})" 33 34 def usb_hid_interface_protocol(subclass, protocol): 35 if subclass == 0x00 and protocol == 0x00: 36 return "None" 37 elif subclass == 0x01: 38 if protocol == 0x00: 39 return "None" 40 elif protocol == 0x01: 41 return "Keyboard" 42 elif protocol == 0x02: 43 return "Mouse" 44 45 return f"Unknown (0x{protocol:02X})" 46 47 def usb_interface_polling_rate(speed, interval): 48 if speed >= 3: 49 return f"{interval * 125} μs ({8000 // interval} Hz)" 50 else: 51 return f"{interval} ms ({1000 // interval} Hz)" 52 53 if __name__ == '__main__': 54 devices = usb.core.find(find_all=True) 55 56 for device in devices: 57 try: 58 configuration = device.get_active_configuration() 59 except NotImplementedError: 60 continue 61 62 hid_interfaces = [] 63 for interface in configuration.interfaces(): 64 if interface.bInterfaceClass == USB_INTERFACE_CLASS_HID: 65 hid_interfaces.append(interface) 66 67 if len(hid_interfaces) > 0: 68 print(f"{device.manufacturer} {device.product} ({device.idVendor:04X}:{device.idProduct:04X}:{device.bcdDevice:04X}), {usb_device_spec(device.bcdUSB)} {usb_device_speed(device.speed)}") 69 70 for interface in hid_interfaces: 71 print(f"└─ HID Interface {interface.bInterfaceNumber}") 72 subclass = interface.bInterfaceSubClass 73 protocol = interface.bInterfaceProtocol 74 print(f" ├─ Subclass: {usb_hid_interface_subclass(subclass)}") 75 print(f" ├─ Protocol: {usb_hid_interface_protocol(subclass, protocol)}") 76 77 for endpoint in interface.endpoints(): 78 endpoint_address = endpoint.bEndpointAddress & 0xF 79 endpoint_direction = "IN" if endpoint.bEndpointAddress & 0x80 else "OUT" 80 print(f" └─ Endpoint {endpoint_address} {endpoint_direction}") 81 print(f" ├─ Endpoint Size: {endpoint.wMaxPacketSize} bytes") 82 print(f" └─ Polling Rate: {usb_interface_polling_rate(device.speed, endpoint.bInterval)}")