Skip to content
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ void loop() {

The connection callback (via attachConnectionCallback()) notifies you when a compatible keyboard is connected.

Tested with: Oldschool classic Dell L100 and brand new “gaming” modern GamingX Trust keyboards.


### Mouse
Reading Mouse Information
The mouse class provides a callback that returns a structure containing mouse event data. The structure is defined as follows:
Expand Down Expand Up @@ -85,16 +88,19 @@ void onMouseEvent(const HIDMouseEvent &mouseEvent) {
usbMouse.attachMouseEventCallback(onMouseEvent);
```

Tested with: basic wired mouse Genius X-Scroll GM-110020, new model GamingX Trust “gaming” mouse and Dell WM 126 wireless mouse.


### Keyboard and Mouse
In order to use two (or more) HID devices connected via a USB hub to your Portenta C33 board, please open "tusb_config.h" and make sure that "CFG_TUH_HUB" is set to value 1, and that "CFG_TUH_HID" is set to the number of HID devices you intend to connect to your Arduino (2 in this example).
Please also keep in mind that some keyboards and mice which include advanced illumination features might draw more power than the Arduino is able to provide on its
USB-A port and might therefore lead to a reset or failure to be enumerated by the board. Ideally, use basic USB keyboards and mice, these should work best.

### Temp. Development instructions
Before all the changes get merged into the core, you will have to do some modifications to get this library to compile.

1. Enable TinyUSB HID Host support

In the core by modify [variants/PORTENTA_C33/tusb_config.h](https://github.com/arduino/ArduinoCore-renesas/blob/main/variants/PORTENTA_C33/tusb_config.h).
On line 106, add `#define CFG_TUH_HID 1`.
Check [this PR](https://github.com/arduino/ArduinoCore-renesas/compare/main...cristidragomir97:ArduinoCore-renesas:hid_host_c33) for more information.

2. Enable weak callback for `tuh_hid_report_received_cb`
When enabling CFG_TUH_HID in tusb_config.h, the stack will expect a tuh_hid_report_received_cb callback to be defined in every sketch, preventing any sketch that doesn't have anything to do with the HID Host stack from compiling. The hid_host.h file defines weak callbacks in order to prevent this issue, but the TU_ATTR_WEAK is prefixed to most callbacks except fortuh_hid_report_received_cb. These changes add this attribute, allowing any sketch to compile.

Check [this PR](https://github.com/arduino/tinyusb/pull/3/commits/e3e9dd066cd64d98de6bd19d2920fec3019b71c4) for more information.
Check [this PR](https://github.com/arduino/ArduinoCore-renesas/compare/main...cristidragomir97:ArduinoCore-renesas:hid_host_c33) for more information.
16 changes: 16 additions & 0 deletions examples/Barcode/Barcode.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* This example shows how to use the Arduino Portenta C33 USBHIDHost library to read barcodes like the ones printed on common
* products packaging.
*
* By connecting a handheld barcode reader to the USB-A port on the mid-carrier board of your
* Arduino Portenta C33, you should immediately be able to read standard 13-digit bar codes on
* any ordinary commercial product packaging.
* Please note that barcodes longer than 13 digits will result in "Invalid character detected, resetting..." messages being printed.
*
* Instructions:
* 1. Connect your Arduino Portenta C33 to a mid-carrier board;
* 2. Upload this sketch to the board;
* 3. Open the Serial Monitor and chose the same baud rate as used in the sketch;
* 4. Connect your barcode scanner to the USB-A connector on the mid-carrier board and scan away.
*/

#include <Arduino.h>
#include <Arduino_USBHIDHost.h>

Expand Down
25 changes: 21 additions & 4 deletions examples/Keyboard/Keyboard.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/*
* This simple example shows how to read keyboard data by both listening for events and polling for available character data in the internal buffers of the USB HID Host.
* There are two general ways user input can be detected, either by constantly checking for the state of a buffer (or pin, for example), which we refer to as the "polling" method, or
* by having some event fire as soon as the user input (key press in this case) is detected, which, in turn, calls a function we registered previously with the lower layers.
* The below example demonstrates both these methods of capturing user input.
*
* Instructions:
* 1. Connect your Arduino Portenta C33 to a mid-carrier board;
* 2. Upload this sketch to the Portenta;
* 3. Open the Serial Monitor and chose 115200 as baud rate;

* 4. Connect your keyboard to the USB-A connector and any keypress should be printed to the console window.
*/

#include <Arduino.h>
#include <Arduino_USBHIDHost.h>

Expand All @@ -7,8 +21,9 @@ void onKeyboardConnected() {
Serial.println("Keyboard connected (callback).");
}

// This function will now be called every time a key is pressed by the user, as a single event
void onKeyboardEvent(uint8_t key) {
Serial.print("Keyboard event (callback): ");
Serial.print("Key pressed (event callback): ");
Serial.println((char) key);
}

Expand All @@ -17,15 +32,17 @@ void setup() {
while (!Serial);

kb.attachConnectionCallback(onKeyboardConnected);
kb.attachKeyboardEventCallback(onKeyboardEvent);
kb.attachKeyboardEventCallback(onKeyboardEvent); // Register callback to get the keystrokes via events
kb.begin();
}

void loop() {
kb.poll();
kb.poll(); // This function will continuously check if a key has been pressed, this is generally referred to as "polling"

// If keystrokes were registered, we enter a second loop and print out the entire buffer
while (kb.available() > 0) {
char c = kb.read();
Serial.print(c);
Serial.print("Key pressed (polling detection): ");
Serial.println(c);
}
}
52 changes: 36 additions & 16 deletions examples/KeyboardAndMouse/KeyboardAndMouse.ino
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
/*
* This simple example demonstrates how to read mouse and keyboard data, by connecting these devices at the same time to the Portenta, via a USB hub
*
* In order to use two (or more) HID devices connected via a USB hub to your Portenta C33 board, please open "tusb_config.h" below (right click -> Go To Definition)
* and make sure that "CFG_TUH_HUB" is set to value 1, and that "CFG_TUH_HID" is set to the number of HID devices you intend to connect to your Arduino (2 in this example).
Comment on lines +4 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be necessary. If it is, we need to fix that.

* Please also keep in mind that some keyboards and mice which include advanced illumination features might draw more power than the Arduino is able to provide on its
* USB-A port and might therefore lead to a reset or failure to be enumerated by the board. Ideally, use basic USB keyboards and mice, these should work best.
*
* Instructions:
* 1. Connect your Arduino Portenta C33 to a mid-carrier board;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or use a USB Hub

* 2. Upload this sketch to the Portenta;
* 3. Open the Serial Monitor and chose the same baud rate as used in the sketch;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* 3. Open the Serial Monitor and chose the same baud rate as used in the sketch;
* 3. Open the Serial Monitor and chose 115200 as baud rate;

* 4. Connect a USB hub to the USB-A connector on the mid-carrier board;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...or a USB-Hub with PD directly

* 5. Now connect your keyboard and mouse to the USB hub and check the printed output on the console when pressing a key on the keyboard or moving the mouse.
*/

#include <Arduino.h>
#include <Arduino_USBHIDHost.h>
#include <tusb_config.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ew. Is this really necessary? If so, this header file should be included in the library's umbrella header


// Global device instances
USBHIDKeyboard kb;
USBHIDMouse ms;

HIDMouseEvent mouseEvent;
bool eventReceived = false;

// Keyboard connection callback
void onKeyboardConnected() {
Serial.println("Keyboard connected (callback).");
Expand All @@ -22,15 +42,12 @@ void onMouseConnected() {
}

// Mouse movement/button event callback
// Note here the use of the "eventReceived" global variable. Since this function is called in an interrupt context,
// we cannot do the processing and printing out of data using Serial.print, inside the interrupt, because it takes too much time.
// Therefore, we set a global flag to "true", which is then checked in the "loop", outside of the ISR (interrupt service routine), then set back to "false".
// An even better and more robut, but also more complex, way of handling this is by using a buffer queue for the mouse data and a state machine to process it.
void onMouseEvent(const HIDMouseEvent &event) {
Serial.print("Mouse event (callback) - Buttons: ");
Serial.print(event.buttons);
Serial.print(", x: ");
Serial.print(event.xMovement);
Serial.print(", y: ");
Serial.print(event.yMovement);
Serial.print(", wheel: ");
Serial.println(event.wheelMovement);
eventReceived = true;
}

void setup() {
Expand All @@ -55,12 +72,15 @@ void loop() {
kb.poll();
ms.poll();

// Optional: Read keyboard characters from buffer
while (kb.available() > 0) {
char c = kb.read();
Serial.print("Buffered keystroke: ");
Serial.println(c);
}

// You can also process mouse state if needed
if(eventReceived){
Serial.print("Mouse event (callback) - Buttons: ");
Serial.print(mouseEvent.buttons);
Serial.print(", x: ");
Serial.print(mouseEvent.xMovement);
Serial.print(", y: ");
Serial.print(mouseEvent.yMovement);
Serial.print(", wheel: ");
Serial.println(mouseEvent.wheelMovement);
eventReceived = false;
}
}
12 changes: 12 additions & 0 deletions examples/Mouse/Mouse.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
/*
* This simple example shows how to read mouse data, like cursor position and key states, by registering a callback and listening for events
*
* Instructions:
* 1. Connect your Arduino Portenta C33 to a mid-carrier board;
* 2. Upload this sketch to the board;

* 3. Open the Serial Monitor and chose the same baud rate (115200 in this case) as used in the sketch;
* 4. Connect your mouse to the USB-A connector and any movement or keypress should be printed as data to the console.
* Please note that the scroll wheel data works inconsistently and might not function correctly with your mouse.
*/

#include <Arduino.h>
#include <Arduino_USBHIDHost.h>

Expand Down