Skip to content

Commit ebf9dcb

Browse files
authored
Merge pull request #4689 from dhalbert/dynamic-usb-descriptors
Dynamic USB descriptors
2 parents 03a4f85 + 843598e commit ebf9dcb

File tree

143 files changed

+2055
-7764
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+2055
-7764
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ jobs:
245245
- "feather_mimxrt1011"
246246
- "feather_mimxrt1062"
247247
- "feather_nrf52840_express"
248-
- "feather_radiofruit_zigbee"
249248
- "feather_stm32f405_express"
250249
- "fluff_m0"
251250
- "gemma_m0"

WEBUSB_README.md

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -62,33 +62,4 @@ The tinyusb examples already include a "WebUSB serial" example.
6262
Basically, this feature was ported into CircuitPython by pulling code snippets out of the
6363
tinyusb example, and putting them where they best belonged in the CircuitPython codebase.
6464

65-
There was one complication:
66-
67-
tinyusb uses C preprocessor macros to define things like USB descriptors.
68-
69-
CircuitPython uses a Python program (tools/gen_usb_descriptor.py) to create USB descriptors (etc.)
70-
using "helper objects" from another repo (adafruit_usb_descriptor). This means some of the example
71-
code had to be adapted to the new programing model, and gen_usb_descriptor gained new command-line
72-
options to control the generated code.
73-
74-
The generated files go into the "build" directory, look for autogen_usb_descriptor.c and
75-
genhdr/autogen_usb_descriptor.h.
76-
77-
78-
Also worth pointing out - the re-use of the CDC connect/disconnect mechanism is not actually part
79-
of the WebUSB standard, it's more of "common idiom". We make use of it here because we need to know
80-
when we should be paying attention to the WebUSB serial interface, and when we should ignore it..
81-
82-
## Possible future work areas
83-
84-
The current code uses the existing Python infrastructure to create the Interface descriptor, but
85-
simply outputs the code snippets from the original tinyusb demo code to create the WEBUSB_URL,
86-
BOS, and MS_OS_20 descriptors. I suppose additional work could be done to add these to the
87-
adafruit_usb_descriptor project, and then gen_usb_descriptor.py could be modified to make use
88-
of them.
89-
90-
Program gen_usb_descriptor.py creates objects for most interface types, regardless of whether or
91-
not they are actually enabled. This increases the size of a generated string table. I made the
92-
new vendor-interface-related code not do this (because some of the ARM platforms would no longer
93-
build), but I did not go back and do this for the other interface types (CDC, MIDI, HID, etc.)
94-
Some FLASH savings are probably possible if this is done.
65+
### TODO: This needs to be reworked for dynamic USB descriptors.

docs/shared_bindings_matrix.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ def get_settings_from_makefile(port_dir, board_name):
155155

156156
settings = {}
157157
for line in contents.stdout.split('\n'):
158-
m = re.match(r'^([A-Z][A-Z0-9_]*) = (.*)$', line)
158+
# Handle both = and := definitions.
159+
m = re.match(r'^([A-Z][A-Z0-9_]*) :?= (.*)$', line)
159160
if m:
160161
settings[m.group(1)] = m.group(2)
161162

locale/circuitpython.pot

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ msgstr ""
8787
msgid "%q list must be a list"
8888
msgstr ""
8989

90+
#: shared-bindings/usb_hid/Device.c
91+
msgid "%q must be 1-255"
92+
msgstr ""
93+
9094
#: shared-bindings/memorymonitor/AllocationAlarm.c
9195
msgid "%q must be >= 0"
9296
msgstr ""
@@ -99,6 +103,10 @@ msgstr ""
99103
msgid "%q must be >= 1"
100104
msgstr ""
101105

106+
#: shared-bindings/usb_hid/Device.c
107+
msgid "%q must be None or 1-255"
108+
msgstr ""
109+
102110
#: shared-module/vectorio/Polygon.c
103111
msgid "%q must be a tuple of length 2"
104112
msgstr ""
@@ -604,6 +612,11 @@ msgstr ""
604612
msgid "Can't set CCCD on local Characteristic"
605613
msgstr ""
606614

615+
#: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c
616+
#: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c
617+
msgid "Cannot change USB devices now"
618+
msgstr ""
619+
607620
#: shared-bindings/_bleio/Adapter.c
608621
msgid "Cannot create a new Adapter; use _bleio.adapter;"
609622
msgstr ""
@@ -646,7 +659,7 @@ msgid "Cannot record to a file"
646659
msgstr ""
647660

648661
#: shared-module/storage/__init__.c
649-
msgid "Cannot remount '/' when USB is active."
662+
msgid "Cannot remount '/' when visible via USB."
650663
msgstr ""
651664

652665
#: ports/atmel-samd/common-hal/microcontroller/__init__.c
@@ -1576,6 +1589,11 @@ msgstr ""
15761589
msgid "No long integer support"
15771590
msgstr ""
15781591

1592+
#: shared-module/usb_hid/__init__.c
1593+
#, c-format
1594+
msgid "No more than %d HID devices allowed"
1595+
msgstr ""
1596+
15791597
#: shared-bindings/wifi/Radio.c
15801598
msgid "No network with that ssid"
15811599
msgstr ""
@@ -2184,6 +2202,14 @@ msgstr ""
21842202
msgid "USB Error"
21852203
msgstr ""
21862204

2205+
#: supervisor/shared/safe_mode.c
2206+
msgid "USB devices need more endpoints than are available."
2207+
msgstr ""
2208+
2209+
#: supervisor/shared/safe_mode.c
2210+
msgid "USB devices specify too many interface names."
2211+
msgstr ""
2212+
21872213
#: shared-bindings/_bleio/UUID.c
21882214
msgid "UUID integer value must be 0-0xffff"
21892215
msgstr ""
@@ -3497,6 +3523,10 @@ msgstr ""
34973523
msgid "no such attribute"
34983524
msgstr ""
34993525

3526+
#: shared-bindings/usb_hid/__init__.c
3527+
msgid "non-Device in %q"
3528+
msgstr ""
3529+
35003530
#: ports/nrf/common-hal/_bleio/Connection.c
35013531
msgid "non-UUID found in service_uuids_whitelist"
35023532
msgstr ""

main.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@
9595
#include "shared-module/network/__init__.h"
9696
#endif
9797

98-
#if CIRCUITPY_USB_CDC
99-
#include "shared-module/usb_cdc/__init__.h"
98+
#if CIRCUITPY_USB_HID
99+
#include "shared-module/usb_hid/__init__.h"
100100
#endif
101101

102102
#if CIRCUITPY_WIFI
@@ -299,6 +299,10 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
299299
supervisor_allocation* heap = allocate_remaining_memory();
300300
start_mp(heap);
301301

302+
#if CIRCUITPY_USB
303+
usb_setup_with_vm();
304+
#endif
305+
302306
found_main = maybe_run_list(supported_filenames, &result);
303307
#if CIRCUITPY_FULL_BUILD
304308
if (!found_main){
@@ -500,11 +504,15 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
500504
}
501505
#endif
502506

503-
// TODO(tannewt): Allocate temporary space to hold custom usb descriptors.
504507
filesystem_flush();
505508
supervisor_allocation* heap = allocate_remaining_memory();
506509
start_mp(heap);
507510

511+
#if CIRCUITPY_USB
512+
// Set up default USB values after boot.py VM starts but before running boot.py.
513+
usb_set_defaults();
514+
#endif
515+
508516
// TODO(tannewt): Re-add support for flashing boot error output.
509517
bool found_boot = maybe_run_list(boot_py_filenames, NULL);
510518
(void) found_boot;
@@ -517,7 +525,27 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
517525
boot_output_file = NULL;
518526
#endif
519527

528+
529+
#if CIRCUITPY_USB
530+
531+
// Some data needs to be carried over from the USB settings in boot.py
532+
// to the next VM, while the heap is still available.
533+
// Its size can vary, so save it temporarily on the stack,
534+
// and then when the heap goes away, copy it in into a
535+
// storage_allocation.
536+
537+
size_t size = usb_boot_py_data_size();
538+
uint8_t usb_boot_py_data[size];
539+
usb_get_boot_py_data(usb_boot_py_data, size);
540+
#endif
541+
520542
cleanup_after_vm(heap);
543+
544+
#if CIRCUITPY_USB
545+
// Now give back the data we saved from the heap going away.
546+
usb_return_boot_py_data(usb_boot_py_data, size);
547+
#endif
548+
521549
}
522550
}
523551

@@ -527,6 +555,11 @@ STATIC int run_repl(void) {
527555
filesystem_flush();
528556
supervisor_allocation* heap = allocate_remaining_memory();
529557
start_mp(heap);
558+
559+
#if CIRCUITPY_USB
560+
usb_setup_with_vm();
561+
#endif
562+
530563
autoreload_suspend();
531564
new_status_color(REPL_RUNNING);
532565
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
@@ -586,7 +619,14 @@ int __attribute__((used)) main(void) {
586619

587620
run_boot_py(safe_mode);
588621

589-
// Start serial and HID after giving boot.py a chance to tweak behavior.
622+
// Start USB after giving boot.py a chance to tweak behavior.
623+
#if CIRCUITPY_USB
624+
// Setup USB connection after heap is available.
625+
// It needs the heap to build descriptors.
626+
usb_init();
627+
#endif
628+
629+
// Set up any other serial connection.
590630
serial_init();
591631

592632
#if CIRCUITPY_BLEIO
@@ -640,6 +680,10 @@ void gc_collect(void) {
640680
common_hal_bleio_gc_collect();
641681
#endif
642682

683+
#if CIRCUITPY_USB_HID
684+
usb_hid_gc_collect();
685+
#endif
686+
643687
#if CIRCUITPY_WIFI
644688
common_hal_wifi_gc_collect();
645689
#endif

0 commit comments

Comments
 (0)