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 ?)
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 ?)