To read data from a mouse in CircuitPython, you must use a device that supports USB Host, such as the Metro RP2350 or Feather RP2040 USB Host.
Feather RP2040 USB Host Wiring
Connecting to the Feather RP2040 USB Host requires plugging in a USB mouse to the Feather's Host port.
Metro RP2350 USB Host Wiring
Connecting to the Metro RP2350 USB Host port requires soldering pins to the broken out USB Host connections as shown in this guide page. Make the following connections between the Metro USB Host pins and USB Host breakout cable.
- GND to Black wire
- D+ to Green wire
- D- to White wire
- 5V to Red red
Fruit Jam Mini Computer
Connecting to the Fruit Jam requires plugging in a USB mouse to one of the Fruit Jam's USB Host ports.
As of CircuitPython version 10.0.0-beta.3, the wired USB mouse works on CircuitPython when connected directly to the USB Host pins or port. Prior releases of CircuitPython required connecting through a USB hub such as the CH334F.
Demo Code: Read Data
This example uses the USB Host API to read data from the mouse and prints out the relevant values to the serial console. The CircuitPython USB Host API is made to mimic PyUSB from CPython.
To read data from the mouse, the code must first scan the connected devices and find one with a boot mouse endpoint. Once a mouse device and endpoint are found, the code will try to read data from them in the main loop. If no data is sent, it will timeout and simply keep trying again until data is present. Once it reads data from the mouse, it will print any buttons that are pressed along with the delta X and delta Y values that represent how far the mouse has been moved and in which directions.
The list BUTTONS is created with values "left", "right", and "middle". The order and indexes of these values align with the mouse protocol, which will use bits in the same positions to denote whether each button is being pressed or not.
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
This example is made for a basic mouse with
two buttons and a wheel that can be pressed.
It assumes there is a single mouse connected to USB Host.
"""
import array
import usb.core
import adafruit_usb_host_descriptors
# button names
# This is ordered by bit position.
BUTTONS = ["left", "right", "middle"]
# scan for connected USB device and loop over any found
for device in usb.core.find(find_all=True):
# print device info
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
print(device.manufacturer, device.product)
print(device.serial_number)
# try to find mouse endpoint on the current device.
mouse_interface_index, mouse_endpoint_address = (
adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device)
)
if mouse_interface_index is not None and mouse_endpoint_address is not None:
mouse = device
print(
f"mouse interface: {mouse_interface_index} "
+ f"endpoint_address: {hex(mouse_endpoint_address)}"
)
# detach the kernel driver if needed
if mouse.is_kernel_driver_active(0):
mouse.detach_kernel_driver(0)
# set configuration on the mouse so we can use it
mouse.set_configuration()
break
# buffer to hold mouse data
buf = array.array("b", [0] * 8)
# main loop
while True:
try:
# attempt to read data from the mouse
# 20ms timeout, so we don't block long if there
# is no data
count = mouse.read(0x81, buf, timeout=20)
except usb.core.USBTimeoutError:
# skip the rest of the loop if there is no data
continue
# string with delta x, y values to print
out_str = f"{buf[1]},{buf[2]}"
# loop over the button names
for i, button in enumerate(BUTTONS):
# check if each button is pressed using bitwise AND shifted
# to the appropriate index for this button
if buf[0] & (1 << i) != 0:
# append the button name to the string to show if
# it is being clicked.
out_str += f" {button}"
print(out_str)
Here is a sample output using the Adafruit mouse. If you have a different mouse, the identification information will likely be different, but the functionality should be the same.
Page last edited September 12, 2025
Text editor powered by tinymce.