USB HID Examples#
Overview#
CanMV provides HID input wrappers under the usb module, allowing direct reading from USB keyboards, mice, and touch input.
The current firmware includes 3 accompanying examples:
src/canmv/resources/examples/03-Machine/usb_hid_keyboard.pysrc/canmv/resources/examples/03-Machine/usb_hid_mouse.pysrc/canmv/resources/examples/03-Machine/usb_hid_touch.py
This set of examples has the following features:
Loops and retries opening when no device is plugged in
Supports automatic reconnection after device disconnection
The keyboard example outputs key events and parsed characters
The mouse example outputs button edges, relative displacement, and scroll wheel
The touch example outputs press status, pressure, and coordinates
Usage Prerequisites#
The development board works in USB Host mode
A USB HID device has been plugged in, such as a keyboard, mouse, or USB touch device
The firmware includes the
usbmodule and USB HID host support
Keyboard Example#
import time
from usb import Keyboard
def open_keyboard():
keyboard = Keyboard(timeout_ms=1000, auto_reconnect=True)
while True:
try:
keyboard.open()
info = keyboard.info()
print("USB keyboard ready:", info)
return keyboard
except OSError as err:
print("waiting for USB keyboard:", err)
time.sleep_ms(500)
keyboard = open_keyboard()
while True:
frame = keyboard.read(1000)
if not frame:
continue
events = frame["events"]
if not events:
continue
text = frame["text"]
chars = frame["chars"]
for keycode, value in events:
if value == Keyboard.VALUE_PRESSED:
state = "pressed"
elif value == Keyboard.VALUE_REPEAT:
state = "repeat"
else:
state = "released"
print("keycode=%d state=%s" % (keycode, state))
if chars:
print(
"parsed chars=%s text=%r ctrl=%s shift=%s alt=%s meta=%s caps_lock=%s"
% (
chars,
text,
frame["ctrl"],
frame["shift"],
frame["alt"],
frame["meta"],
frame["caps_lock"],
)
)
Output Description#
events: Raw keyboard event frame, each element is(keycode, value)chars: List of character encodings parsed from this frametext: Byte string parsed from this frame, e.g.b"abc"ctrl/shift/alt/meta/caps_lock: Current modifier key states
Keyboard Example Output Reference#
USB keyboard ready: {'kind': 'keyboard', 'name': 'Logitech USB Keyboard', 'path': '/dev/hidk0', ...}
keycode=34 state=pressed
parsed chars=(103,) text=b'g' ctrl=False shift=False alt=False meta=False caps_lock=False
keycode=34 state=released
Mouse Example#
import time
from usb import Mouse
def open_mouse():
mouse = Mouse(timeout_ms=1000, auto_reconnect=True)
while True:
try:
mouse.open()
info = mouse.info()
print("USB mouse ready:", info)
print("button masks:", Mouse.BTN_LEFT_MASK, Mouse.BTN_RIGHT_MASK, Mouse.BTN_MIDDLE_MASK)
return mouse
except OSError as err:
print("waiting for USB mouse:", err)
time.sleep_ms(500)
mouse = open_mouse()
while True:
frame = mouse.read(1000)
if not frame:
continue
moved = frame["has_rel"] or frame["has_abs"]
button_edge = frame["pressed_mask"] or frame["released_mask"]
wheel_move = frame["wheel"] or frame["hwheel"]
if not moved and not button_edge and not wheel_move:
continue
print(
"buttons=%d pressed=%d released=%d rel=(%d,%d) abs=(%d,%d) wheel=(%d,%d)" % (
frame["buttons"],
frame["pressed_mask"],
frame["released_mask"],
frame["rel_x"],
frame["rel_y"],
frame["abs_x"],
frame["abs_y"],
frame["wheel"],
frame["hwheel"],
)
)
Mouse Example Output Reference#
USB mouse ready: {'kind': 'mouse', 'name': 'USB Optical Mouse', 'path': '/dev/hidm0', ...}
button masks: 1 2 4
buttons=1 pressed=1 released=0 rel=(12,-3) abs=(0,0) wheel=(0,0)
Touch Example#
import time
from usb import Touch
def open_touch():
touch = Touch(timeout_ms=1000, auto_reconnect=True)
while True:
try:
touch.open()
info = touch.info()
print("USB touch ready:", info)
return touch
except OSError as err:
print("waiting for USB touch device:", err)
time.sleep_ms(500)
touch = open_touch()
while True:
frame = touch.read(1000)
if not frame:
continue
active = frame["touch_seen"] or frame["buttons"] or frame["pressure"]
moved = frame["has_abs"] or frame["has_rel"]
if not active and not moved:
continue
print(
"down=%s pressure=%d buttons=%d abs=(%d,%d) rel=(%d,%d)" % (
frame["touch_down"],
frame["pressure"],
frame["buttons"],
frame["abs_x"],
frame["abs_y"],
frame["rel_x"],
frame["rel_y"],
)
)
Common Usage Suggestions#
Use Auto-Reconnect#
It is recommended to enable this when creating the object:
kbd = Keyboard(timeout_ms=1000, auto_reconnect=True)
This way, after the USB HID device is unplugged, subsequent poll(), read(), info() calls will attempt to automatically recover.
Distinguish Between Raw Keys and Parsed Characters#
For shortcut keys, game controls, or raw key handling, use
eventsFor text input, use
charsandtext
Handle Timeout Returns#
poll(timeout_ms): returnsFalseon timeoutread(timeout_ms): returnsNoneon timeout
So in the example, it is common to check first:
frame = keyboard.read(1000)
if not frame:
continue
Frequently Asked Questions#
What to do when keyboard key characters don’t match the actual input?#
Please update to the firmware version that includes the latest USB HID fixes. The current implementation has corrected letter key parsing based on Linux input keycode mapping, and supports combination handling of Ctrl, Shift, and Caps Lock.
Will the script stop after the device is unplugged?#
If auto_reconnect=True is enabled, the script will enter a waiting-for-reconnection state; it will automatically resume after reinserting a device of the same type.
Do mouse and touch use the same return structure?#
Both return pointer-type frame structures, but the mouse mainly uses relative coordinates and button bits, while touch more commonly uses absolute coordinates, pressure, and touch_down.
