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 all commits
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)
45 changes: 45 additions & 0 deletions examples/usb_host_descriptors_find_boot_keyboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import array

import usb

import adafruit_usb_host_descriptors

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 keyboard endpoints on this device
keyboard_interface_index, keyboard_endpoint_address = (
adafruit_usb_host_descriptors.find_boot_keyboard_endpoint(device)
)
# 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

# detach device from kernel if needed
if keyboard.is_kernel_driver_active(0):
keyboard.detach_kernel_driver(0)

# 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 keyboard
try:
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 keyboard
continue

for b in buf:
print(hex(b), end=" ")
print()