summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Banks <kevin@firia.com>2021-02-03 18:51:48 -0600
committerKevin Banks <kevin@firia.com>2021-02-03 18:51:48 -0600
commitf2067730cb1986d0b325cd22545da1a0d48920aa (patch)
treeb3290a59d080ed791e2af09263267db452139cba
parent215a56c920b64d522e505d20e1480859fd0ea333 (diff)
Code cleanup and added a WEBUSB_README file
-rw-r--r--WEBUSB_README.md91
-rw-r--r--tools/gen_usb_descriptor.py25
2 files changed, 95 insertions, 21 deletions
diff --git a/WEBUSB_README.md b/WEBUSB_README.md
new file mode 100644
index 000000000..a4b9c4c3e
--- /dev/null
+++ b/WEBUSB_README.md
@@ -0,0 +1,91 @@
+<!--
+SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
+
+SPDX-License-Identifier: MIT
+-->
+
+# WebUSB Serial Support
+
+To date, this has only been tested on one port (esp32s2), on one board (espressif_kaluga_1).
+
+## What it does
+
+If you have ever used CircuitPython on a platform with a graphical LCD display, you have probably
+already seen multiple "consoles" in use (although the LCD console is "output only").
+
+New compile-time option CIRCUITPY_USB_VENDOR enables an additional "console" that can be used in
+parallel with the original (CDC) serial console.
+
+Web pages that support the WebUSB standard can connect to the "vendor" interface and activate
+this WebUSB serial console at any time.
+
+You can type into either console, and CircuitPython output is sent to all active consoles.
+
+## How to enable
+
+Update your platform's mpconfigboard.mk file to enable and disable specific types of USB interfaces.
+
+CIRCUITPY_USB_HID = xxx
+CIRCUITPY_USB_MIDI = xxx
+CIRCUITPY_USB_VENDOR = xxx
+
+On at least some of the hardware platforms, the maximum number of USB endpoints is fixed.
+For example, on the ESP32S2, you must pick only one of the above 3 interfaces to be enabled.
+
+Original espressif_kaluga_1 mpconfigboard.mk settings:
+
+CIRCUITPY_USB_HID = 1
+CIRCUITPY_USB_MIDI = 0
+CIRCUITPY_USB_VENDOR = 0
+
+Settings to enable WebUSB instead:
+
+CIRCUITPY_USB_HID = 0
+CIRCUITPY_USB_MIDI = 0
+CIRCUITPY_USB_VENDOR = 1
+
+Notice that to enable VENDOR, we had to give up HID. There may be platforms that can have both.
+
+## Implementation Notes
+
+CircuitPython uses the tinyusb library.
+
+The tinyusb library already has support for WebUSB serial.
+The tinyusb examples already include a "WebUSB serial" example.
+
+ Sidenote - The use of the term "vendor" instead of "WebUSB" was done to match tinyusb.
+
+Basically, this feature was ported into CircuitPython by pulling code snippets out of the
+tinyusb example, and putting them where they best belonged in the CircuitPython codebase.
+
+There was one complication:
+
+tinyusb uses C preprocessor macros to define things like USB descriptors.
+
+CircuitPython uses a Python program (tools/gen_usb_descriptor.py) to create USB descriptors (etc.)
+using "helper objects" from another repo (adafruit_usb_descriptor). This means some of the example
+code had to be adapted to the new programing model, and gen_usb_descriptor gained new command-line
+options to control the generated code.
+
+The generated files go into the "build" directory, look for autogen_usb_descriptor.c and
+genhdr/autogen_usb_descriptor.h.
+
+
+Also worth pointing out - the re-use of the CDC connect/disconnect mechanism is not actually part
+of the WebUSB standard, it's more of "common idiom". We make use of it here because we need to know
+when we should be paying attention to the WebUSB serial interface,and when we should ignore it..
+
+## Possible future work areas
+
+The current code uses the existing Python infrastructure to create the Interface descriptor, but
+simply outputs the code snippets from the original tinyusb demo code to create the WEBUSB_URL,
+BOS, and MS_OS_20 descriptors. I suppose additional work could be done to add these to the
+adafruit_usb_descriptor project, and then gen_usb_descriptor.py could be modified to make use
+of them.
+
+Program gen_usb_descriptor.py creates objects for most interface types, regardless of whether or
+not they are actually enabled. This increases the size of a generated string table. I made the
+new vendor-interface-related code not do this (because some of the ARM platforms would no longer
+build), but I did not go back and do this for the other interface types (CDC, MIDI, HID, etc.)
+Some FLASH savings are probably possible if this is done.
+
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 05d35ffc4..ad68d0ea9 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -2,21 +2,6 @@
#
# SPDX-License-Identifier: MIT
-def fix_note(note):
- index = note.rfind(" object at")
- if index >= 0:
- note = note[:index] + ">"
- return note
-
-def fix_notes(notes):
- count = len(notes)
- index = 0
- while index < count:
- notes[index] = fix_note(notes[index])
- index += 1
-
- return notes
-
import argparse
import os
@@ -389,8 +374,7 @@ audio_control_interface = standard.InterfaceDescriptor(
# Audio streaming interfaces must occur before MIDI ones.
audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces
-# TODO New code goes here to create vendor objects
-# Starting out with a clone-and-modify of the HID descriptors
+# Vendor-specific interface, for example WebUSB
vendor_endpoint_in_descriptor = standard.EndpointDescriptor(
description="VENDOR in",
bEndpointAddress=args.vendor_ep_num_in | standard.EndpointDescriptor.DIRECTION_IN,
@@ -407,9 +391,9 @@ vendor_endpoint_out_descriptor = standard.EndpointDescriptor(
if 'VENDOR' in args.devices:
vendor_interface = standard.InterfaceDescriptor(
description="VENDOR",
- bInterfaceClass=0xff, # vendor.VENDOR_CLASS,
- bInterfaceSubClass=0x00, #vendor.VENDOR_SUBCLASS_???,,
- bInterfaceProtocol=0x00, #vendor.VENDOR_PROTOCOL_NONE,
+ bInterfaceClass=0xff, # Vendor-specific
+ bInterfaceSubClass=0x00,
+ bInterfaceProtocol=0x00,
iInterface=StringIndex.index("{} VENDOR".format(args.interface_name)),
subdescriptors=[
vendor_endpoint_in_descriptor,
@@ -546,7 +530,6 @@ for descriptor in descriptor_list:
b = bytes(descriptor)
notes = descriptor.notes()
- notes = fix_notes(notes) # for comparision of files beteen runs
i = 0
# This prints each subdescriptor on a separate line.