Is it possible to make Double RAWHID for Teensy41? Just like that have done in Trible Serial.

My guess is it is probably possible, although it would take some work! And there may be some hidden gotcha's

The RAWHID usb type is mode up of two sort of RAWHID devices, the RAWHID and the SEREMU...
You would need a new type like defined in usb_desc.h
Which copies USB_RAWHID area, you might be able to take over an existing USB Type.

You would then need to to add a section within usb_desc.c that is sort of a copy of the RAWHID_INTERFACE section.

Probably need changes in usb.c - to call out to maybe configure the second one.

usb_rawhid.c/usb_rawhid.h - would probably need it to define a second instance of the usb_rawhid_class, like:
extern usb_rawhid_class RawHID2;
The class and functions, maybe need to be updated to know which end points to use for each instance...

which maybe you need to add in to usb_inst.cpp

And then there might be issues on the Host side... (Or not)
That is with the test program it has in the test program things like:
Code:
// C-based example is 16C0:0480:FFAB:0200
    r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200);
    if (r <= 0) {

So, it has the VID:pID of the Teensy raw hid (16c0:0480): Maybe with the second one would have a different USAGE Page: Usage value
First here is the FFAB:0200 maybe if both are FFAB:0200 it will return both of them? I don't know.

Sorry I know I am just throwing out some general steps to take to find out how hard it might be to make work

Good luck
 
Kurt covered most of the steps. But at the risk of duplicating, here's another attempt.

The first step is editing the USB descriptors, which you do with usb_desc.h and usb_desc.c. The "descriptors" are just arrays of bytes that get sent when your PC asks what kind of USB device has just been connected. You'll see the .h file is a long list of all the USB types we support in Arduino IDE's Tools > USB Type menu. The actual data arrays are in the .c file. Which get compiled and some of their specific numbers are based on the defines from the .h file.

If you're using Windows, the good news is it usually will pay attention to your changes in the descriptors after each upload after Teensy reboots. That's much easier than USB Serial, where Windows stupidly stores the previously detected info in its registry and refuses to recognize your changes to the descriptors. In that situation you much alter the vendor ID, device ID or BCD rev number in the main device descriptor, otherwise Windows pretty much disregards whatever info you give in the descriptors and uses what it previously saw and stored in the Windows Registry. MacOS and Linux don't do this... it's a Windows thing and really frustrating if you are developing your own custom USB device. But with HID, Windows seems to do the sensible thing and just use the fresh descriptor info.

Windows, MacOS and Linux all read the device descriptor first, which has only very basic info (vendor ID, etc). Then they read the config descriptor to learn what features you are offering. You'll see it's huge with a lot idef stuff. Basically for each of the possible things you could have defined in the .h file, the .c file has a block of data which becomes part of the config descriptor to tell your computer about that capability. You'll see the config descriptor data for RawHID starting at line 1212. You'll need to add another block of similar data, and similar defines in the .h file. Maybe call it RAWHID_INTERFACE2. Of course you'll need to assign unique endpoint numbers, increase NUM_INTERFACE and NUM_ENDPOINTS, etc.

The other descriptor data you'll need to duplicate is the rawhid_report_desc[] array. This is the "report" descriptor. This is where the usage and usage page numbers are given. If you just reuse the existing data, then your PC will see 2 HID interfaces with all identical numbers, which isn't very useful. At least the usage number needs to change so you can run different programs on your PC to talk to each RawHID interface. You'll see the config descriptor has the size of the report desciptor. Technically you should edit that to your new array name, but the size will probably be the same anyway. The place you need to edit so Teensy answers is your new report descriptor in the usb_descriptor_list[] array, around line 2817. After your PC reads the config descriptor, it will know you have 2 HID interface (or really 3 with the serial emu interface too). It will then try to read the report descriptors for each of them. For all the other changes you've just altered arrays that were already in the code. That descriptor list array is the critical location to edit so Teensy answers the request for a new report descriptor what wasn't part of the prior code. Even through your new report descriptor data will be just a copy of the existing one with just the usage number changed, from you computer's perspective it's a distinctively new descriptor.

The other distinctively new thing you need is the code which actually communicates on the USB endpoints, which your computer learned about from the config descriptor data. For that, you'll make a copy of rawhid.c and rawhid.h and change the names of every function and the C++ class name. The compiler will mostly "help" you with this stuff, you'll get compile errors for anything you've duplicated and not renamed. Intially you might have an overwhelming number of compile errors about duplicate names. Just approach it methodically and try to keep in mind those frustrating errors are actually telling you precisely where the problems exist which is a lot better than things just not working without any idea why. The tricky part is diligence to make sure you've used the new names in all the descriptor data and other places you edit, because the new stuff is just copies of the old with minor edits (mostly just using the new defines) so any place that references would be syntactically correct with either new or old, as far as the compiler is concerned.

Then you'll need to edit just a couple more places. Text search for RAWHID_INTERFACE, because everywhere you find it you'll need to add another chunk of code for your RAWHID_INTERFACE2 define. Most of them should be pretty obvious what to do. For example, in usb.c at line 456 you would add code to call your usb_rawhid2_configure() function (of whatever unique name you gave to your code). This particular edit is what causes your code to actually enable the USB endpoints to become ready for communication. You'll see similarly obvious edits to make in usb_inst.cpp.

If you get stuck, the difficult part is figuring out what's wrong. Linux kernel messages (eg "sudo dmesg --follow" or "tail -f /var/log/syslog") sometime give nice hints. There are both software-only and (expensive) hardware-based ways to watch the USB communication. The USB-IF website has a USB 2.0 Command Verifier program (which historically has been picky about only supporting certain USB ports & hubs) that can tell you whether your descriptor data complies with the USB standards.

You might also create a fork of the core library on github for the sake of sharing your USB edits. If we can see the complete edits you've attempted, it might be long shot, but there's a chance one of us might notice what's wrong.
 
Last edited:
If you're using Windows I highly recommend USBDeview. ( www.nirsoft.net/system_tools )

USBDeview is a small utility that lists all USB devices that currently connected to your computer, as well as all USB devices that you previously used.
For each USB device, extended information is displayed: Device name/description, device type, serial number (for mass storage devices), the date/time that device was added, VendorID, ProductID, and more...
USBDeview also allows you to uninstall USB devices that you previously used, and disconnect USB devices that are currently connected to your computer.
You can also use USBDeview on a remote computer, as long as you login to that computer with admin user.

USBDeview.jpg
 
Back
Top