Custom HID hack

Status
Not open for further replies.

Etienne

Well-known member
Hi,

I've been digging around Teensy core to be able to do any custom HID device that can be configured in the sketch code.

I found a way (an ugly one I think), by adding an empty new HID interface like one would do to create a new HID type (by touching usb_desc.h, usb_desc.c, etc...), except that the report descriptor has to be given by the main application.

Here is the principle :

Normaly in usb_desc.c I should have :

#ifdef CUSTOM_HID_INTERFACE
{0x2200, CUSTOM_HID_INTERFACE, custom_hid_report_desc, sizeof(custom_hid_report_desc) },
{0x2100, CUSTOM_HID_INTERFACE, config_descriptor + CUSTOM_HID_DESC_OFFSET, 9},
#endif

where custom_hid_report_desc is the report descriptor of my HID device, but instead, I've put :

#ifdef CUSTOM_HID_INTERFACE
{0x2200,CUSTOM_HID_INTERFACE,config_descriptor + CUSTOM_HID_INTERFACE_DESC_POS,0xffff},
{0x2100, CUSTOM_HID_INTERFACE, config_descriptor + CUSTOM_HID_DESC_OFFSET, 9},
#endif

and I've written a function that looks for an entry with the size == 0xffff (I told you it's ugly), and when I find it, I overwrite the device infos, and put my custom descriptor address and length instead, then I patch the interface infos and put my custom tx and rx report sizes, etc...
I've used similar hacks to patch the vendor and product ids, bcdDevice, and device name.

I added a hook at the beginning or usb_init(), just before usb_init_serialnumber(), so I can patch all these descriptors before the usb initialization takes place.

It works. I've created a Custom HID and a Custom HID + Serial device (added in boards.txt)

In the end, in the user sketch, you just have to put these few initialisations (this is an example):

const uint8_t customHidReportDescriptor[] = {put your report descriptor here};
const uint8_t inReportSize= your_in_report_size;
const uint8_t outReportSize= your_out_report_size;
const uint8_t productName[] = {14,3,'C',0,'u',0,'s',0,'t',0,'o',0,'m',0};

void usb_init_cutomhid()
{
usb_set_custom_hid_report_descriptor(customHidReportDescriptor, sizeof(customHidReportDescriptor), inReportSize, outReportSize);
usb_set_product_name((struct usb_string_descriptor_struct *)&productName);
usb_set_device_ids(0x16C0,0x748d,0x4541);
}

You'll find all the modified core files along with an example sketch here :
http://www.nodeblue.org/downloads/teensy_3_custom_hid_mod.zip
I tried to avoid modifying the core as much as I can, so things might not be at the right place.

Just copy the hardware folder to your Arduino ide (tested with Arduino 1.8.5 and TeensyDuino 1.41, I've put only the files I've changed), and use the test_custom_hid sketch to test an example with 8 buttons and 3 analog axis.

Now I have 2 problems:

1) The emulated serial doesn't work, when I open the serial monitor it says it's online, but nothing is received (in the example I print a number every seconds).

I have no clue of where to search, I've using USBLyzer to look are USB traffic, but no packets seems to be sent to the PC.

2) With the SEREMU_INTERFACE having index 0 and CUSTOM_HID_INTERFACE having index 1 (like in the zip i'm giving), the debug window in the game controller properties on windows is empty, while it is seen by other tools, like http://html5gamepad.com/. If I put SEREMU_INTERFACE index to 1 and CUSTOM_HID_INTERFACE to 0, the under windows it is seen (but then USBLyzer complains, saying that interfaces index should be increasing).

Note that changing pid or bcdDevice to avoid Windows USB info cache problems doesn't solve anything (don't know what the hell windows is doing with USB device caching, anyone knows where to clean registry for that ?)
 
Problems 1) and 2) solved by using the same Product ID as the standard Keyboard/Mouse/Joystick USB Type = 0x0482.
I guess the teensy gateway fake serial expects only certain VID & PID.

However since windows had already seen this USB device, I still had the name "Keyboard/Mouse/Joystick" in the game controllers window (joy.cpl), and the icon of a keyboard in the device/printers window instead of a game pad.
I'm on Windows 10 by the way.
I removed the device in the device manager, unplugged / replugged, the game pad icon came back.
I went in windows registry, to :
HKEY_CURRENT_USER\System\CurrentControlSet\Control \MediaProperties\PrivateProperties\Joystick\OEM

I deleted VID_16C0&PID_0482, and then the name in the game controllers window changed to "Custom".
 
Ok, I merged the custom hid code in the latest beta, it works well. Great improvement in compile time :)
I did my own fake serial monitor in which I can choose the PID I use, so that's ok.
However I still have a problem, the auto-upload feature of the Teensy loader seems to work the same way as the serial monitor, it doesn't work if I use an unknown PID.
Is it possible to specify a vid/pid or a serial number to the teensy_post_compile command ? (I'm not using Arduino IDE to compile/upload).
I've looked a teensy loader cli, but could not find any option for that neither. I mean, Is there a way to upload a .hex to a specific Teensy ? (the problem arise also when having several Teensy boards connected).

If I use a known PID, like the one for the keyboard/mouse/joystick 0x0482, I have windows 8 that uses cached info for the device and it's not recognized as it should.
Do you know how to really clean windows registry about hid ? I tried many things but none worked, including removing the device in the devices/printers window.
The registry key I found in the previous post is only about the name. I found other keys but I could not delete them (in HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB\VID_16C0&PID_0482) the
 
Last edited:
Ok now I send a Hid feature request with the magic sequence to the seremu interface, so I can reboot the board I want :)
So the only problem left seems to be windows usb caching mystery :(
 
Status
Not open for further replies.
Back
Top