Code cleanup and added a WEBUSB_README file
This commit is contained in:
parent
215a56c920
commit
f2067730cb
91
WEBUSB_README.md
Normal file
91
WEBUSB_README.md
Normal file
@ -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.
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user