Skip to content
luni64 edited this page Mar 24, 2020 · 16 revisions

Tutorial

HID devices usually don't need a device driver which makes them very attractive for the user. Just plug it in and it works. All HID devices exchange data organized in so called reports. To find out how the data in these reports is organized the host (PC) requests a report descriptor when it detects a new device. For Teensy rawHID the report is a simple 64 byte data-chunk which makes data exchange very easy for both, the host and the device application.

HID devices can not actively send data to the PC. Instead, they prepare a report and inform the host about it. As soon as it finds time it will collect the report from the device.

Sending data from the Teensy

Using the Teensy RawHID usb mode is very easy. If, for example, you want to send data to the PC you simply fill a 64 byte buffer with your data and provide it for collecting by usb_rawhid_send(void* buffer, int timeout). The first parameter is the address of the 64 byte buffer, the second parameter is a timeout in ms. If the host didn't collect the report after the timeout the teensy will abort the operation.

Here a working example which sends an incrementing value in the first byte of the report. You can download this and the following examples from here: https://github.com/TeensyUser/doc/tree/master/examples/HID

uint8_t report[64];

void setup(){}

void loop()
{
    report[0] = millis()/100;
    usb_rawhid_send(report, 1000);
    delay(100);
}

Receiving data on the PC

Generated HID devcies

Receiving data on the PC is nearly as easy as sending it from the Teensy. However, it is important to understand that RAWHID exposes two HID interfaces, the first one is the actual RAWHID, the second one is a SEREMU interface. Operating systems (at least Win10, what about LINUX?) generate a dedicated HID device for each HID interface a device provides. Thus, if you plug in the Teeny two HID devices, one RAWHID and one SEREMU device will appear.

You can distinguish them by having a look at their usagepage and usages:

  • RAWHID: usage = 0xFFAB, usage page: 0x0200
  • SEREMU: usage = 0xFFC9, usage page: 0x0004

The following Win10 (dotNet, c#) example shows how to read in those packages. It uses Mike ò Brians hidlibrary to talk to the HID devices. The application looks for a device with the correct VID/PID and the RAWHID usage. If it finds one it waits for HID Reports from the Teensy and prints the first byte of the report on the console.

using HidLibrary;
using System;
using System.Linq;

namespace receiver
{
    class Program
    {
        static void Main(string[] args)
        {
            var teensy = HidDevices.Enumerate(0x16C0, 0x0486)    // 0x486 -> usb type raw hid
                        .Where(d => d.Capabilities.Usage==0x200) // usage 0x200 -> RawHID usage
                        .FirstOrDefault();                       // take the first one we find on the USB bus

            while (teensy != null)
            {
                var report = teensy.ReadReport();                // request a report from the teensy
                Console.WriteLine(report.Data[0]);               // and write the first byte on the console
            }
        }
    }
}

Sending reports to the Teensy

The following example demonstrates sending RAWHID reports from a PC to a Teensy. Instead of a boring incrementing number, this time we read a random advice slip from adviceslip.com and send it to the Teensy.

using HidLibrary;
using System;
using System.Json;
using System.Linq;
using System.Net;

namespace hid
{
    class Program
    {
        static void Main(string[] args)
        {
            var teensy = HidDevices.Enumerate(0x16C0, 0x0486).Where(d => d.Capabilities.Usage == 512).FirstOrDefault();
            if (teensy == null || !teensy.IsConnected) return;

            for(int loops = 0; loops< 10; loops++)               // don't read too much data from the web page...
            {
                String slip = new WebClient().DownloadString(@"https://api.adviceslip.com/advice");  // read a slip from adviceslip.com
                String advice = JsonValue.Parse(slip)["slip"]["advice"];                             // extract the advice from the json result

                HidReport report = teensy.CreateReport();        // Generate an empty report
                for(int i = 0; i< advice.Take(63).Count(); i++ ) // and copy the characters into it.
                {                                                // limit to 63 bytes to ensure the report always has a EOS (\0) at the end
                    report.Data[i] = (byte) advice[i];
                }
                teensy.WriteReport(report);                      // send report to teensy
                Console.WriteLine(advice);                       // echo on console
            }
        }
    }
}

The receiving code on the Teensy is as simple as this:

void setup()
{
}

void loop()
{
    char buf[64];

    if(usb_rawhid_recv(buf, 10) > 0)  // Wait for a received raw hid report
    {
      Serial.println(buf);            // and print it on Serial
    }
}

And here some output, written by the Teensy (note that we limited the text to 64byte in this simple example)

image

Both, firmware and software can be downloaded from here: https://github.com/TeensyUser/doc/tree/master/examples/HID

Forum posts:


Teensy hidlisten

Teensy 2 only: https://www.pjrc.com/teensy/hid_listen.html

Teensy gateway

Teensy Gateway

winhidlisten

Winhidlisten

Clone this wiki locally