-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Dynamic USB descriptors #4689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic USB descriptors #4689
Conversation
I like this approach very much. |
Does this allow setting multiple keyboard HID descriptors and their order? |
No, multiple HID device descriptors are not yet supported. |
Here are my first API thoughts. I haven't looked at the code yet. Thanks for working on this!
I'm not a fan of the common Another thing to consider is whether this will work in the longer term where some interfaces are disabled and others are enabled. It might be better to set them all at once so you have one source for errors. What would happen if someone tries to enable too many things at once?
I don't think you can because USB can restart at any time. |
@dhalbert I hate to keep bringing the pirkey_m0 up , but this removes pulseio from it again. Was that intentional? Should I give up on it... |
Ah -- it's more than just that -- I put pulseio back in -- now get an IOError: USB Busy -- I'll look into that but it may be time to move on... |
The removal of pulseio was unintentional; I will put it back. If you are getting USB errors, that is something else, and may reflect a larger problem. Try a Trinket M0 or similar; I did test, but not after I did a lot of the build rework. |
I opened #4724 |
Based on the above, I have been trying to improve my mouse jiggler to make the presence of CircuitPython stealth. No sure exactly what I did wrong (more than one thing likely)... I tried my best to upgrade my CPX to the latest CP, upgrade all the mpy and run this code as code.py... but It still fail. When using boot.py nothing seems to occurs. |
From my understanding, that slide position check and the disabling of USB descriptors needs to be in |
So indeed boot.py is needed, and I was confused because the output of It is very hard to troubleshoot and understand what is happening... but I also need to convince Windows 10 that the filesystem is clean. Any ejection when CIRCUITPY is visible make this trick stop to work for me and the drive keep reappering. Is the mass storage temporary visible to windows, and once the popup appear it is not possible to hide the drive??? Here is my minimal
|
That code looks correct. You should be able to get a clean unmount in Windows by doing an "Eject" from the USB icon in the taskbar. But that should not affect whether this code runs. boot.py only runs after a hard reset (power-cycle, reset button press, or similar). It does not run after auto-reload due to editing code.py or another file, or if you type ctrl-D in the REPL. |
Hi, this code: import usb_cdc
import storage
import digitalio
import microcontroller
buttona = digitalio.DigitalInOut(microcontroller.pin.GPIO15)
buttona.direction = digitalio.Direction.INPUT
buttona.pull = digitalio.Pull.UP
thisstat = not buttona.value
buttona.deinit()
if thisstat:
print("disable_usb_drive")
storage.disable_usb_drive()
print("usb_cdc.enable(console=False, data=True)")
usb_cdc.enable(console=False, data=True)`
else:
print("nothing changed")
print("boot.py done") works for me on a MagTag. What other USB-devices (end-points) can I deactivate to get: If I try this the boot process is stuck in a loop! (I think because "safe-mode" is not working on a ESP32-S2 !? |
Do The safe mode problem has an issue at #4766. (If you put your entire code in a pair of triple-backquotes it will be marked as a single block of code.) EDIT: and if you add |
I somehow broke the boot.py file which makes the file system read-only.
I think it should be the other way round: If something is wrong with boot.py, the filesystem should be always writeable so you are able to fix the error. Renaming boot.py via REPL didn't work but formating the drive resets it completly. |
If the filesystem is corrupted, then the metadata is probably damaged (e.g., the directory entries). It can't be recovered, so we or the host computer make it read-only so no worse damage will happen. Read about the best way to edit files and avoid corruption here: |
Ok, because the error got written to boot_out.txt it looked liked an internal behaviour of circuitpython. Is there an updated sample boot.py from your first post? |
What is your boot.py? That would be the easiest. Also see the documentation: https://circuitpython.readthedocs.io/en/latest/shared-bindings/index.html. I will be writing a Learn Guide shortly. This is all very new. I am working on boot HID devices at the moment. |
FYI tested this last nite with RP2040, very successful! |
I've just copied the sample you gave in this thread in the first post #4689 (comment) but it outputs an error in boot_out.txt
Edit: According to this doc, out_report_length is allowed to be 0 https://circuitpython.readthedocs.io/en/latest/shared-bindings/usb_hid/ |
I ran also into errors in boot.py during coding.... |
I tested disabling CDC and MSD on a QTPy M0, using touchio pins. Works great, thank you! |
Changed line 19 to try to match what's shown in adafruit/circuitpython#4689
I think I'm missing a memo here. Between the information at the top of this pull request and @todbot's Gist from 5/17/21, I got to Billfred/Serpente-iPad-HID@affb16e for boot.py on my Serpente R2. Reset the board, and boot_out.txt reads:
Mass storage is also remounting, which is an even clearer sign that something is going off the rails since it sure looks like I'm disabling storage in boot.py. Any insight in what I'm doing wrong? |
@Billfred Please see https://learn.adafruit.com/customizing-usb-devices-in-circuitpython and https://circuitpython.readthedocs.io/en/latest/README.html for a more complete version of the latest information> if you have trouble please ask in https://adafru.it/discord or https://forums.adafruit.com. |
Implements dynamic USB descriptors, including HID.
Fixes #4351, fixes #1015, fixes #4242, fixes #2087.
Not yet included: ability to change interface names (#4433), boot keyboard (#1136).
#620 (touchpad) would implemented as a custom HID device and a library.
This will break the existing VENDOR WebUSB implementation and that will have to be redone.
API Summary [edited to reflect final API after PR was merged]
All configuration is done in
boot.py
.usb_hid.Device.MOUSE
,.KEYBOARD
, and.CONSUMER_CONTROL
. Gamepad, sys_control, etc, are all dropped, but could be supplied by the user. You can choose any combination of these, or roll your own.All the configuration routines use the generalconfigure_usb()
, rather than just, say,enabled()
) so that in the future they might take more arguments other than just bools or a list (e.g. interface names, multiple HID devices for a separate boot keyboard, etc.)Implementation Details
The RAM needed is allocated dynamically according to size, when possible. A few things are small fixed arrays when it wasn't practical or worth it to make it dynamic. The boolean enabled/disabled choices are just remembered in static storage. The defaults are set before
boot.py
runs.For the HID device list, it's trickier. The default list is set, and may be changed in
boot.py
. Whenboot.py
finishes, before the VM goes away, the HID report descriptor is built. Since it might not be safe to leave it on the heap, it's copied up to themain.c
stack temporarily, then the VM is stopped, then it's put back in astorage_allocation
before the VM and heap are re-created for the REPL or code.py. Before the REPL or code.py VM is started, the other descriptors are built and put instorage_allocation
s or in static storage if they are fixed length. Then USB is initialized.The HID devices are remembered in a short static array (up to 8 devices) between VM runs.
We could free the
storage_allocation
s after USB starts, but it's hard to tell when, and I'm not sure the RAM can be made use of anyway, since it's just in a a random place. Perhaps more work could be done on that later, but we're talking a few hundred bytes.The Python scripts that built the descriptors before are no longer needed. The descriptor fixups that used to be done in Python (put this interface number here and here, etc.) are now in C. The
usb_descriptors
submodule could be removed but requires some git surgery which I need to look up.Tested on a Metro M4:
midi_simpletest.py
works and MIDI can be disabledI expect build failures due to size.
Sample boot.py [EDIT:
black
mangled the comments in the first version of this rather badly. Fixed.]