Skip to content

add find_boot_keyboard function and example #7

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

Merged
merged 3 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions adafruit_usb_host_descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
47 changes: 47 additions & 0 deletions examples/usb_host_descriptors_find_boot_keyboard.py
Original file line number Diff line number Diff line change
@@ -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()