How to receive raw HID using usb host?

CM207

Member
Hello,

I am currently working on receiving and outputting raw HID data from a device (e.g., mouse or USB receiver) connected to the USB host of a Teensy 4.1. While I am confident that the wiring is correct - since I can successfully receive all data using the MouseController class - I encounter an issue when attempting to receive raw HID data. Specifically, I only see the message “Waiting for data...” once, and no further data is received/printed.

Could you advise on what I might be missing or how I can resolve this?

Thank you for your assistance.

Here is my approach:
C:
#include <USBHost_t36.h>

USBHost usb_host;
USBHIDParser usb_hid_parser(usb_host);
RawHIDController raw_hid_controller(usb_host);

// Callback function to handle received HID data
bool handleHIDData(uint32_t usage, const uint8_t *data, uint32_t len) {
  Serial.print("Received HID data (Usage: ");
  Serial.print(usage);
  Serial.println("):");
 
  for (uint32_t i = 0; i < len; i++) {
    Serial.print(data[i], HEX);  // Print each byte in hexadecimal format
    Serial.print(" ");
  }
  Serial.println();
 
  return true; 
}

void setup() {
  Serial.begin(115200);
  usb_host.begin();
  Serial.println("Waiting for data...");

  // Attach the receive callback function to print HID data when received
  raw_hid_controller.attachReceive(handleHIDData);
}

void loop() {
  usb_host.Task();
}
 
The rawhid class is setup to handle the PJRC RAWHID setup... That is as explained on the page:

The claim code starts off like:
Code:
hidclaim_t RawHIDController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage)
{
    // only claim RAWHID devices currently: 16c0:0486
#ifdef USBHOST_PRINT_DEBUG
    USBHDBGSerial.printf("Rawhid Claim: %x:%x usage: %x\n", dev->idVendor, dev->idProduct, topusage);
#endif

    if (dev->idVendor != 0x16c0) return CLAIM_NO;  //  NOT PJRC
    if (mydevice != NULL && dev != mydevice) return CLAIM_NO;
    if (usage_) return CLAIM_NO;            // Only claim one

    if (fixed_usage_ ) {
        if (fixed_usage_ != topusage) return CLAIM_NO;         // See if we want specific one and if so is it this one
    } else if (dev->idProduct != 0x486) return CLAIM_NO;    // otherwise mainly used for RAWHID Serial type.
So it will only claim the HID object:
if the vendor ID is PJRC (16c0) and a few others as PJRC does not own all of 16c0...

It then by default only claim the product ID 0x486
Which is what PJRC sets a teensy to if you select the USB type of RAW HID...
You can overwrite the Usage to something else by setting it on the 2nd parameter of the constructor.

Could more of these rules be relaxed... Probably. Or you could simply start off from some other class, like the
HIDDumper class in the HIDDeviceinfo example sketch.
 
Here is a sketch that is quick and dirty extracts from rawhid and my hid dumper code...

It does show, input from my mouse I plugged in:
Code:
Received HID data (Usage: 65538):
0 A 2 0
Received HID data (Usage: 65538):
0 F 0 0
Received HID data (Usage: 65538):
0 14 0 0
Received HID data (Usage: 65538):
0 1A FE 0
Received HID data (Usage: 65538):
0 1F FD 0
Received HID data (Usage: 65538):
0 27 FE 0
Received HID data (Usage: 65538):
0 2A FE 0
Received HID data (Usage: 65538):
0 2F FE 0

Note: it may work on some devices and not others.

Why? Some devices may require some handshake to get them working. For example
they may need for the code to select which output report to output, or to say that the we are in the right state.

Other notes: There have been requests similar to this where for example someone wishes to plug something like a keyboard into a teensy,
and have intercept some keyboard data and maybe inject other data.

This requires that the Teensy be setup with it's USB Descriptors and the like for the right USB mode, like keyboard.
And while most simple keyboards that run in "Boot" mode have similar data, there are other keyboards that do not.
Also there could be several Interfaces associated with the keyboard on the device. Like a few HID interfaces. One for normal data,
another for items like media with volume up/down, another for system keys, etc. The host device will want to also parse the data and
if for example the default Teensy USB descriptor for keyboard does not match, the actual devices, you will need to modify the data
before forwarding...
 

Attachments

  • HID_simple_dump-240926a.zip
    4.8 KB · Views: 30
Back
Top