To read data from a mouse in Arduino, you must use a device which supports USB Host such as the Metro RP2350 or Feather RP2040 USB Host. Right now the Metro RP2350 only works when the wired mouse is connected through a USB hub such as the CH334F.
Feather RP2040 USB Host Wiring
Simply plug the mouse into the USB Host port on the Feather RP2040 USB Host
Metro RP2350 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 CH334F host connection opposite the USB C connector.
- GND to GND with Black or Blue
- D+ to D+ with Green
- D- to D- with White
- 5V to 5V with Red
Note that the data pins are swapped on the Metro compared to the CH334F breakout. On the Metro D- is next to 5V, whereas on the CH334F D- is next to GND.
Be sure to connect D- on the breakout to D- on the Metro, and D+ on the breakout to D+ on the Metro.
USB Host is under active development. As of Pico-PIO-USB version 0.7.1 and TinyUSB version 3.4.4, the wired USB Mouse only works on the Metro RP2350 with Arduino when connected through a USB hub such as the CH334F.
Install the Libraries
You can install the libraries for this project using the Library Manager in the Arduino IDE.
Click the Library Manager icon, search for Adafruit TinyUSB Arduino, and select the Adafruit TinyUSB Library.
If asked about dependencies click "Install All".
Then install the Pico PIO USB library. Click the Library Manager icon menu item again, search for PIO USB, and select the Pico PIO USB library by sekigon-gonnoc.
Code Prep
The code consists of a main .ino program file and two header files. The header files store configuration for USB host on the RP2040/RP2350 and HID device reports for the mouse. You'll need all three of these files to properly compile and run the project.
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries // // SPDX-License-Identifier: MIT /********************************************************************* Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information Copyright (c) 2019 Ha Thach for Adafruit Industries All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* This example demonstrates use of usb host with a standard HID boot mouse. * - Host depends on MCU: * - rp2040: bit-banging 2 GPIOs with Pico-PIO-USB library (roothub port1) * * Requirements: * - For rp2040: * - Pico-PIO-USB library * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1 * - Provide VBus (5v) and GND for peripheral */ // USBHost is defined in usbh_helper.h #include "usbh_helper.h" #include "tusb.h" #include "Adafruit_TinyUSB.h" #include "hid_mouse_reports.h" bool printed_blank = false; void setup() { Serial.begin(115200); // configure pio-usb: defined in usbh_helper.h rp2040_configure_pio_usb(); // run host stack on controller (rhport) 1 // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the // host bit-banging processing works done in core1 to free up core0 for other works USBHost.begin(1); delay(3000); Serial.print("USB D+ Pin:"); Serial.println(PIN_USB_HOST_DP); Serial.print("USB 5V Pin:"); Serial.println(PIN_5V_EN); } void loop() { USBHost.task(); Serial.flush(); } //--------------------------------------------------------------------+ // HID Host Callback Functions //--------------------------------------------------------------------+ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { Serial.printf("HID device mounted (address %d, instance %d)\n", dev_addr, instance); // Start receiving HID reports if (!tuh_hid_receive_report(dev_addr, instance)) { Serial.printf("Error: cannot request to receive report\n"); } } void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { Serial.printf("HID device unmounted (address %d, instance %d)\n", dev_addr, instance); } void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { if (len > 0){ //debug print report data // Serial.print("Report data: "); // for (int i = 0; i < len; i++) { // if (i == 0 || i == 3){ // Serial.print(report[i], HEX); // Serial.print(" "); // }else { // i==1 or i==2 // Serial.print((int8_t)report[i]); // Serial.print(" "); // } // } // Serial.println(); Serial.print("X: "); Serial.print((int8_t)report[1]); Serial.print(" "); Serial.print("Y: "); Serial.print((int8_t)report[2]); Serial.print(" "); if (report[BYTE_BUTTONS] != BUTTON_NEUTRAL){ if ((report[BYTE_BUTTONS] & BUTTON_LEFT) == BUTTON_LEFT){ Serial.print("Left "); } if ((report[BYTE_BUTTONS] & BUTTON_RIGHT) == BUTTON_RIGHT){ Serial.print("Right "); } if ((report[BYTE_BUTTONS] & BUTTON_MIDDLE) == BUTTON_MIDDLE){ Serial.print("Middle "); } } Serial.println(); } // Continue to receive the next report if (!tuh_hid_receive_report(dev_addr, instance)) { Serial.println("Error: cannot request to receive report"); } }
// SPDX-FileCopyrightText: 2024 Ha Thach for Adafruit Industries // // SPDX-License-Identifier: MIT /********************************************************************* Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information Copyright (c) 2019 Ha Thach for Adafruit Industries All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #ifndef USBH_HELPER_H #define USBH_HELPER_H #ifdef ARDUINO_ARCH_RP2040 // pio-usb is required for rp2040 host #include "pio_usb.h" // Pin D+ for host, D- = D+ + 1 #ifndef PIN_USB_HOST_DP #define PIN_USB_HOST_DP 16 #endif // Pin for enabling Host VBUS. comment out if not used #ifndef PIN_5V_EN #define PIN_5V_EN 18 #endif #ifndef PIN_5V_EN_STATE #define PIN_5V_EN_STATE 1 #endif #endif // ARDUINO_ARCH_RP2040 #ifdef ARDUINO_ARCH_RP2350 // pio-usb is required for rp2040 host #include "pio_usb.h" // Pin D+ for host, D- = D+ + 1 #ifndef PIN_USB_HOST_DP #define PIN_USB_HOST_DP 32 #endif // Pin for enabling Host VBUS. comment out if not used #ifndef PIN_5V_EN #define PIN_5V_EN 29 #endif #ifndef PIN_5V_EN_STATE #define PIN_5V_EN_STATE 1 #endif #endif // ARDUINO_ARCH_RP2350 #include "Adafruit_TinyUSB.h" #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 // USB Host using MAX3421E: SPI, CS, INT #include "SPI.h" #if defined(ARDUINO_METRO_ESP32S2) Adafruit_USBH_Host USBHost(&SPI, 15, 14); #elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2) Adafruit_USBH_Host USBHost(&SPI, 33, 15); #else // Default CS and INT are pin 10, 9 Adafruit_USBH_Host USBHost(&SPI, 10, 9); #endif #else // Native USB Host such as rp2040 Adafruit_USBH_Host USBHost; #endif //--------------------------------------------------------------------+ // Helper Functions //--------------------------------------------------------------------+ #ifdef ARDUINO_ARCH_RP2040 static void rp2040_configure_pio_usb(void) { //while ( !Serial ) delay(10); // wait for native usb Serial.println("Core1 setup to run TinyUSB host with pio-usb"); #ifdef PIN_5V_EN pinMode(PIN_5V_EN, OUTPUT); digitalWrite(PIN_5V_EN, PIN_5V_EN_STATE); #endif pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; pio_cfg.pin_dp = PIN_USB_HOST_DP; #if defined(ARDUINO_RASPBERRY_PI_PICO_W) // For pico-w, PIO is also used to communicate with cyw43 // Therefore we need to alternate the pio-usb configuration // details https://github.com/sekigon-gonnoc/Pico-PIO-USB/issues/46 pio_cfg.sm_tx = 3; pio_cfg.sm_rx = 2; pio_cfg.sm_eop = 3; pio_cfg.pio_rx_num = 0; pio_cfg.pio_tx_num = 1; pio_cfg.tx_ch = 9; #endif USBHost.configure_pio_usb(1, &pio_cfg); } #endif #endif
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries // // SPDX-License-Identifier: MIT // HID reports for standard boot mouse // Byte indices for the gamepad report #define BYTE_BUTTONS 0 // Left, right, middle click buttons #define BYTE_DELTA_X 1 // Mouse movement horizontal #define BYTE_DELTA_Y 2 // Mouse movement vertical #define BUTTON_NEUTRAL 0x00 #define BUTTON_LEFT 0x01 #define BUTTON_RIGHT 0x02 #define BUTTON_MIDDLE 0x04
Upload and Test
Before uploading, you'll need to update some settings in the Boards menu. Select the appropriate board that you are using, either Adafruit Feather RP2040 USB Host, or Adafruit Metro RP2350. Under USB Stack select Adafruit TinyUSB.
Then, upload the sketch to your board. You can use the Serial Monitor in the Arduino IDE for debugging any errors.
Serial Output
The code will connect to the USB mouse and read data coming from it. Delta X and Y values are printed to the serial output, when it detects that buttons are pressed it will print which ones are down into the serial output as well..
Page last edited May 06, 2025
Text editor powered by tinymce.