Configure USB after sketch has already loaded

Status
Not open for further replies.

yeahtuna

Well-known member
I would like to hack teensyduino to allow me to set aspects of my USB descriptor from my sketch. The idea is to start my sketch, read settings from EEPROM, adjust aspects of the USB descriptor, and present the device to the host. Given that I'm willing to hack my way to a solution, is something like this possible?
 
Seems like with an edit to : \hardware\teensy\avr\cores\teensy3\usb_dev.c

Before the call to usb_setup(), I just read a value from EEPROM.

Ideally then in '\cores\teensy3\usb_desc.c' with a second custom/hardcoded defined alternate:: const usb_descriptor_list_t *list;

That one could be used instead in usb_setup()?

EEPROM.h didn't work easy in usb_dev.c so with: 'extern void CheckEEval();' called before it the value in a given EEPROM location could be used after that.

Where I put this in my sketch where I made a global Keeper (rather than returning) to see what was read when called from usb_dev.c when I got to setup():
Code:
#ifdef __cplusplus
extern "C" {
#endif

void CheckEEval() {
  Keeper = EEPROM.read(999);
}

#ifdef __cplusplus
}
#endif
 
Very interesting. I haven't tested it yet, but I managed to get the code to compile. I had no idea that I could do something like that. This opens up lots of opportunities. Thank-you so much.
 
I didn't either … but you asked. It worked as noted so I assume it has no bad side effects reading EEPROM at that point ( I had a write of val++ there and it gave odd results ).

Looking at "teensy3\usb_desc.c" the compile time #ifdef's run deep and wide - so duplicating that file to create the alternate 'const usb_descriptor_list_t *list;' might be best and hardcoding the needed #ifdef'd parts? Then in the usb_dev.c I see those same #ifdef's - but the ones I glanced at were conditioned on values - so hopefully that was just to remove unused code - all the needed ones will need to be #defined and maybe that does the trick? I didn't look beyond that - not sure if other files drop any code based on #ifdef.
 
For now, I'm only interested in being able to change the usage and usage_page of an HID device and I'm guessing that won't be so hard as I wouldn't need to change the size of the descriptor. But this certainly get's me wondering what else I can do with these new found powers.
 
So I tested and was able to modify the HID usage page on the fly. I removed 'static' from the following line of code from usb_dev.c so that I could expose it using extern in usb_dev.h.
Code:
uint8_t rawhid_report_desc[] = {

Then in usb_dev.c, just before the call to usb_setup(), I do the following:
Code:
rawhid_report_desc[4] = LSB(0x0200);
rawhid_report_desc[5] = MSB(0x0000);

I think I'll try your multiple descriptor lists next. That seems like it could be extremely useful.
 
Cool. Sounds promising for your use.

Just figured out why the EEPROM call code with value++ was doing something odd - multiple increments - noted above in p#4.

Something to look for - if this order is right - usb_setup() is called by usb_control() which is called by usb_isr() and that is triggered many times before setup().

If it matters _init_Teensyduino_internal_() is upstream where usb_init() is called and starts that, but Teensy hardware is still coming online there.

So if using the above EEPROM read code - it might be best to read it only the first time - then return/re-use that value on each call after that to not stall or interfere with the process.
 
Just a quick update to this thread. I tested making a second usb_descriptor_list_t and softcoded NUM_ENDPOINTS and NUM_INTERFACES, and was able to selectively load two separate device descriptors--extremely cool stuff. Thank-you for all your help.
 
Cool - Is that working based on read of an EEPROM value?

Nice to know such base elements can change reliably at boot time.

Did you find any gotcha's from what seemed the recurring calls through the USB code as it powers up?
 
Status
Not open for further replies.
Back
Top