Teensy + USB Raw HID + C# = Eureka!

I’ve spent at least 3 days converting my Amp Delay Service from Serial communication to Raw HID communication protocol. My CarPC was using at one point 5 COM ports for the various devices connected to it. Iw was becoming a real pain keeping track of each COM port and the actual device that it represents. So I decided to convert my devices to plain USB devices rather than Serial.

Everything was going great until I tried sending data to Teensy while converting the Amp Delay box. The Amp Delay service needs to ping the Teensy device but for some reason (which is still unknown to me) sending data to the Emulated Serial device doesn’t work.

I’ve tried a handful of 3rd party USB libraries, tried rolling my own, tried synchronous vs overlapped IO. Nothing worked. I just could not send data to the device.

After hours of Googling, I finally stumbled on a solution. Turns out that when Teensy operates in Raw HID mode it presents itself to the PC as two devices:

VID_16C0&PID_0486&MI_00 – Raw HID Device
VID_16C0&PID_0486&MI_01 – Emulated Serial device

The “Serial” object in Arduino can send data to the Emulated Serial device which is the method I used to send the Gauge Pod Sender data to the PC. There seems to be a problem however sending data from the host to the device over this protocol.

The correct solution was:

1. Connect to the RAW HID Device instead.
2. Use RawHID.send and RawHID.read in Arduino code to communicate with the host.

I completely accidentally stumbled upon the RawHID object. It is not documented ANYWHERE. The difference is that Serial.print sends data to the Emulated Serial device and RawHID.send sends it to the RAW HID device.


void SendHID(String text) 
{
 
  uint8_t sendMessage[64]; //buffer
  text.getBytes(sendMessage, text.length()+1); //convert text to bytes

  //fill rest of buffer with zero
  for (int idx = text.length(); idx < 64; idx++)
    sendMessage[idx] = 0;
    
//send to PC, allow 100ms for sending the frame
  int sent = RawHID.send(sendMessage, 100);

}

Another interesting tidbit.

arduino-1.0.3\hardware\teensy\cores\usb_rawhid\usb_private.h

holds the VendorID and ProductID that can be changed. When the sketch is uploaded to the device the values are changed on it. This makes it easy to distinguish multiple Teensy devices on the same PC. By changing the Product ID I can have the Amp Delay box and the Gauge Pod sender uniquely identified and don't have to worry about the program connecting to the wrong box.