|
| 1 | +<!-- |
| 2 | +SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) |
| 3 | +
|
| 4 | +SPDX-License-Identifier: MIT |
| 5 | +--> |
| 6 | + |
| 7 | +# WebUSB Serial Support |
| 8 | + |
| 9 | +To date, this has only been tested on one port (esp32s2), on one board (espressif_kaluga_1). |
| 10 | + |
| 11 | +## What it does |
| 12 | + |
| 13 | +If you have ever used CircuitPython on a platform with a graphical LCD display, you have probably |
| 14 | +already seen multiple "consoles" in use (although the LCD console is "output only"). |
| 15 | + |
| 16 | +New compile-time option CIRCUITPY_USB_VENDOR enables an additional "console" that can be used in |
| 17 | +parallel with the original (CDC) serial console. |
| 18 | + |
| 19 | +Web pages that support the WebUSB standard can connect to the "vendor" interface and activate |
| 20 | +this WebUSB serial console at any time. |
| 21 | + |
| 22 | +You can type into either console, and CircuitPython output is sent to all active consoles. |
| 23 | + |
| 24 | +One example of a web page you can use to test drive this feature can be found at: |
| 25 | + |
| 26 | +https://adafruit.github.io/Adafruit_TinyUSB_Arduino/examples/webusb-serial/index.html |
| 27 | + |
| 28 | +## How to enable |
| 29 | + |
| 30 | +Update your platform's mpconfigboard.mk file to enable and disable specific types of USB interfaces. |
| 31 | + |
| 32 | +CIRCUITPY_USB_HID = xxx |
| 33 | +CIRCUITPY_USB_MIDI = xxx |
| 34 | +CIRCUITPY_USB_VENDOR = xxx |
| 35 | + |
| 36 | +On at least some of the hardware platforms, the maximum number of USB endpoints is fixed. |
| 37 | +For example, on the ESP32S2, you must pick only one of the above 3 interfaces to be enabled. |
| 38 | + |
| 39 | +Original espressif_kaluga_1 mpconfigboard.mk settings: |
| 40 | + |
| 41 | +CIRCUITPY_USB_HID = 1 |
| 42 | +CIRCUITPY_USB_MIDI = 0 |
| 43 | +CIRCUITPY_USB_VENDOR = 0 |
| 44 | + |
| 45 | +Settings to enable WebUSB instead: |
| 46 | + |
| 47 | +CIRCUITPY_USB_HID = 0 |
| 48 | +CIRCUITPY_USB_MIDI = 0 |
| 49 | +CIRCUITPY_USB_VENDOR = 1 |
| 50 | + |
| 51 | +Notice that to enable VENDOR on ESP32-S2, we had to give up HID. There may be platforms that can have both, or even all three. |
| 52 | + |
| 53 | +## Implementation Notes |
| 54 | + |
| 55 | +CircuitPython uses the tinyusb library. |
| 56 | + |
| 57 | +The tinyusb library already has support for WebUSB serial. |
| 58 | +The tinyusb examples already include a "WebUSB serial" example. |
| 59 | + |
| 60 | + Sidenote - The use of the term "vendor" instead of "WebUSB" was done to match tinyusb. |
| 61 | + |
| 62 | +Basically, this feature was ported into CircuitPython by pulling code snippets out of the |
| 63 | +tinyusb example, and putting them where they best belonged in the CircuitPython codebase. |
| 64 | + |
| 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. |
0 commit comments