From 21ab387adb3f6430732476994464493e135fe423 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 23 Apr 2025 14:36:25 -0500 Subject: [PATCH 1/3] add find_boot_keyboard function and example --- adafruit_usb_host_descriptors.py | 36 ++++++++++---- ...usb_host_descriptors_find_boot_keyboard.py | 47 +++++++++++++++++++ 2 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 examples/usb_host_descriptors_find_boot_keyboard.py diff --git a/adafruit_usb_host_descriptors.py b/adafruit_usb_host_descriptors.py index c4a6f00..c02c1ba 100644 --- a/adafruit_usb_host_descriptors.py +++ b/adafruit_usb_host_descriptors.py @@ -14,6 +14,11 @@ from micropython import const +try: + from typing import Literal +except ImportError: + pass + __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_USB_Host_Descriptors.git" @@ -39,6 +44,7 @@ INTERFACE_HID = 0x03 SUBCLASS_BOOT = 0x01 PROTOCOL_MOUSE = 0x02 +PROTOCOL_KEYBOARD = 0x01 def get_descriptor(device, desc_type, index, buf, language_id=0): @@ -77,13 +83,7 @@ def get_configuration_descriptor(device, index): return full_buf -def find_boot_mouse_endpoint(device): - """ - Try to find a boot mouse endpoint in the device and return its - interface index, and endpoint address. - :param device: The device to search within - :return: mouse_interface_index, mouse_endpoint_address if found, or None, None otherwise - """ +def _find_boot_endpoint(device, protocol_type: Literal[PROTOCOL_MOUSE, PROTOCOL_KEYBOARD]): config_descriptor = get_configuration_descriptor(device, 0) i = 0 mouse_interface_index = None @@ -99,7 +99,7 @@ def find_boot_mouse_endpoint(device): if ( interface_class == INTERFACE_HID and interface_subclass == SUBCLASS_BOOT - and interface_protocol == PROTOCOL_MOUSE + and interface_protocol == protocol_type ): found_mouse = True mouse_interface_index = interface_number @@ -111,3 +111,23 @@ def find_boot_mouse_endpoint(device): return mouse_interface_index, endpoint_address i += descriptor_len return None, None + + +def find_boot_mouse_endpoint(device): + """ + Try to find a boot mouse endpoint in the device and return its + interface index, and endpoint address. + :param device: The device to search within + :return: mouse_interface_index, mouse_endpoint_address if found, or None, None otherwise + """ + return _find_boot_endpoint(device, PROTOCOL_MOUSE) + + +def find_boot_keyboard_endpoint(device): + """ + Try to find a boot keyboard endpoint in the device and return its + interface index, and endpoint address. + :param device: The device to search within + :return: keyboard_interface_index, keyboard_endpoint_address if found, or None, None otherwise + """ + return _find_boot_endpoint(device, PROTOCOL_KEYBOARD) diff --git a/examples/usb_host_descriptors_find_boot_keyboard.py b/examples/usb_host_descriptors_find_boot_keyboard.py new file mode 100644 index 0000000..af6ca89 --- /dev/null +++ b/examples/usb_host_descriptors_find_boot_keyboard.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT +import array + +import usb + +import adafruit_usb_host_descriptors + +# lists for mouse interface indexes, endpoint addresses, and USB Device instances +# each of these will end up with length 2 once we find both mice +mouse_interface_indexes = None +mouse_endpoint_addresses = None +keyboard = None + +# scan for connected USB devices +for device in usb.core.find(find_all=True): + # check for boot mouse endpoints on this device + kbd_interface_index, kbd_endpoint_address = ( + adafruit_usb_host_descriptors.find_boot_keyboard_endpoint(device) + ) + # if a boot mouse interface index and endpoint address were found + if kbd_interface_index is not None and kbd_interface_index is not None: + keyboard = device + + # detach device from kernel if needed + if keyboard.is_kernel_driver_active(0): + keyboard.detach_kernel_driver(0) + + # set the mouse configuration so it can be used + keyboard.set_configuration() + +buf = array.array("b", [0] * 8) + +while True: + # try to read data from the mouse + try: + count = keyboard.read(mouse_endpoint_addresses, buf, timeout=10) + + # if there is no data it will raise USBTimeoutError + except usb.core.USBTimeoutError: + # Nothing to do if there is no data for this mouse + continue + + for b in buf: + print(hex(b), end=" ") + print() From 7782b669225851a17f0e6e664b422b819536c473 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 24 Apr 2025 13:05:29 -0500 Subject: [PATCH 2/3] fix references to mice --- ...usb_host_descriptors_find_boot_keyboard.py | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/usb_host_descriptors_find_boot_keyboard.py b/examples/usb_host_descriptors_find_boot_keyboard.py index af6ca89..62dd717 100644 --- a/examples/usb_host_descriptors_find_boot_keyboard.py +++ b/examples/usb_host_descriptors_find_boot_keyboard.py @@ -7,39 +7,37 @@ import adafruit_usb_host_descriptors -# lists for mouse interface indexes, endpoint addresses, and USB Device instances -# each of these will end up with length 2 once we find both mice -mouse_interface_indexes = None -mouse_endpoint_addresses = None +keyboard_interface_index = None +keyboard_endpoint_address = None keyboard = None # scan for connected USB devices for device in usb.core.find(find_all=True): - # check for boot mouse endpoints on this device - kbd_interface_index, kbd_endpoint_address = ( + # check for boot keyboard endpoints on this device + keyboard_interface_index, keyboard_endpoint_address = ( adafruit_usb_host_descriptors.find_boot_keyboard_endpoint(device) ) # if a boot mouse interface index and endpoint address were found - if kbd_interface_index is not None and kbd_interface_index is not None: + if keyboard_interface_index is not None and keyboard_endpoint_address is not None: keyboard = device # detach device from kernel if needed if keyboard.is_kernel_driver_active(0): keyboard.detach_kernel_driver(0) - # set the mouse configuration so it can be used + # set the configuration so the keyboard can be used keyboard.set_configuration() buf = array.array("b", [0] * 8) while True: - # try to read data from the mouse + # try to read data from the keyboard try: - count = keyboard.read(mouse_endpoint_addresses, buf, timeout=10) + count = keyboard.read(keyboard_endpoint_address, buf, timeout=10) # if there is no data it will raise USBTimeoutError except usb.core.USBTimeoutError: - # Nothing to do if there is no data for this mouse + # Nothing to do if there is no data for this keyboard continue for b in buf: From e547a73f277bb2c55ebcd2fd1226d50953e3b3d5 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 24 Apr 2025 13:36:11 -0500 Subject: [PATCH 3/3] fix reference to mouse --- examples/usb_host_descriptors_find_boot_keyboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/usb_host_descriptors_find_boot_keyboard.py b/examples/usb_host_descriptors_find_boot_keyboard.py index 62dd717..9ee9bd6 100644 --- a/examples/usb_host_descriptors_find_boot_keyboard.py +++ b/examples/usb_host_descriptors_find_boot_keyboard.py @@ -17,7 +17,7 @@ keyboard_interface_index, keyboard_endpoint_address = ( adafruit_usb_host_descriptors.find_boot_keyboard_endpoint(device) ) - # if a boot mouse interface index and endpoint address were found + # if a boot keyboard interface index and endpoint address were found if keyboard_interface_index is not None and keyboard_endpoint_address is not None: keyboard = device