summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Banks <kevin@firia.com>2021-01-25 20:37:58 -0600
committerKevin Banks <kevin@firia.com>2021-01-25 20:37:58 -0600
commitfbfb7b68cce3fbcccc423c1013c0c3cabe6a89d0 (patch)
tree4b2dfe8eebef84fc24d1a9225aa5c4fa2b874488
parent9ce33a5771cd6061e81aeaf2b1c4361490c36b08 (diff)
Most of the code we need has been pulled in from the tinyusb webusb_serial demo. Still LOTS to do regarding descriptors.
-rw-r--r--ports/esp32s2/Makefile4
-rw-r--r--ports/esp32s2/mpconfigport.mk2
-rw-r--r--py/circuitpy_defns.mk3
-rw-r--r--py/circuitpy_mpconfig.mk3
-rw-r--r--supervisor/shared/serial.c30
-rw-r--r--supervisor/shared/usb/tusb_config.h1
-rw-r--r--supervisor/shared/usb/usb.c76
-rw-r--r--supervisor/supervisor.mk18
-rw-r--r--tools/gen_usb_descriptor.py53
9 files changed, 184 insertions, 6 deletions
diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile
index aac934782..b4ff0612b 100644
--- a/ports/esp32s2/Makefile
+++ b/ports/esp32s2/Makefile
@@ -164,7 +164,9 @@ LIBS += -lm
endif
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 -DCFG_TUSB_OS=OPT_OS_FREERTOS -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 -DCFG_TUSB_OS=OPT_OS_FREERTOS -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024
+CFLAGS += -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128
+CFLAGS += -DCFG_TUD_VENDOR_RX_BUFSIZE=128 -DCFG_TUD_VENDOR_TX_BUFSIZE=128
######################################
diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk
index 562c60998..2d324e161 100644
--- a/ports/esp32s2/mpconfigport.mk
+++ b/ports/esp32s2/mpconfigport.mk
@@ -30,6 +30,8 @@ CIRCUITPY_ROTARYIO = 1
CIRCUITPY_NVM = 1
# We don't have enough endpoints to include MIDI.
CIRCUITPY_USB_MIDI = 0
+# We have borrowed the VENDOR nomenclature from tinyusb. VENDOR AKA WEBUSB
+CIRCUITPY_USB_VENDOR = 1
CIRCUITPY_WIFI = 1
CIRCUITPY_WATCHDOG ?= 1
CIRCUITPY_ESPIDF = 1
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 21bd5b965..5eb7992b1 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -288,6 +288,9 @@ endif
ifeq ($(CIRCUITPY_USB_MIDI),1)
SRC_PATTERNS += usb_midi/%
endif
+ifeq ($(CIRCUITPY_USB_VENDOR),1)
+SRC_PATTERNS += usb_vendor/%
+endif
ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/%
endif
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index d0145a90f..6e721e1bc 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -270,6 +270,9 @@ CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID)
CIRCUITPY_USB_MIDI ?= 1
CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI)
+CIRCUITPY_USB_VENDOR ?= 1
+CFLAGS += -DCIRCUITPY_USB_VENDOR=$(CIRCUITPY_USB_VENDOR)
+
CIRCUITPY_PEW ?= 0
CFLAGS += -DCIRCUITPY_PEW=$(CIRCUITPY_PEW)
diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c
index 303f89e75..b9feb04f2 100644
--- a/supervisor/shared/serial.c
+++ b/supervisor/shared/serial.c
@@ -47,6 +47,10 @@ busio_uart_obj_t debug_uart;
byte buf_array[64];
#endif
+#if CIRCUITPY_USB_VENDOR
+bool tud_vendor_connected(void);
+#endif
+
void serial_early_init(void) {
#if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX)
debug_uart.base.type = &busio_uart_type;
@@ -66,6 +70,12 @@ void serial_init(void) {
}
bool serial_connected(void) {
+#if CIRCUITPY_USB_VENDOR
+ if (tud_vendor_connected()) {
+ return true;
+ }
+#endif
+
#if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX)
return true;
#else
@@ -74,6 +84,14 @@ bool serial_connected(void) {
}
char serial_read(void) {
+#if CIRCUITPY_USB_VENDOR
+ if (tud_vendor_connected() && tud_vendor_available() > 0) {
+ char tiny_buffer;
+ tud_vendor_read(&tiny_buffer, 1);
+ return tiny_buffer;
+ }
+#endif
+
#if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX)
if (tud_cdc_connected() && tud_cdc_available() > 0) {
return (char) tud_cdc_read_char();
@@ -88,6 +106,12 @@ char serial_read(void) {
}
bool serial_bytes_available(void) {
+#if CIRCUITPY_USB_VENDOR
+ if (tud_vendor_connected() && tud_vendor_available() > 0) {
+ return true;
+ }
+#endif
+
#if defined(DEBUG_UART_TX) && defined(DEBUG_UART_RX)
return common_hal_busio_uart_rx_characters_available(&debug_uart) || (tud_cdc_available() > 0);
#else
@@ -104,6 +128,12 @@ void serial_write_substring(const char* text, uint32_t length) {
common_hal_terminalio_terminal_write(&supervisor_terminal, (const uint8_t*) text, length, &errcode);
#endif
+#if CIRCUITPY_USB_VENDOR
+ if (tud_vendor_connected()) {
+ tud_vendor_write(text, length);
+ }
+#endif
+
uint32_t count = 0;
while (count < length && tud_cdc_connected()) {
count += tud_cdc_write(text + count, length - count);
diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h
index 15d9fabaf..d3a35f537 100644
--- a/supervisor/shared/usb/tusb_config.h
+++ b/supervisor/shared/usb/tusb_config.h
@@ -68,6 +68,7 @@
#define CFG_TUD_MSC 1
#define CFG_TUD_HID CIRCUITPY_USB_HID
#define CFG_TUD_MIDI CIRCUITPY_USB_MIDI
+#define CFG_TUD_VENDOR CIRCUITPY_USB_VENDOR
#define CFG_TUD_CUSTOM_CLASS 0
/*------------------------------------------------------------------*/
diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c
index ff08ade18..9b0cba8da 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -37,6 +37,26 @@
#include "tusb.h"
+#if CIRCUITPY_USB_VENDOR
+#include "genhdr/autogen_usb_descriptor.h"
+
+// The WebUSB support being conditionally added to this file is based on the
+// tinyusb demo examples/device/webusb_serial.
+
+enum
+{
+ VENDOR_REQUEST_WEBUSB = 1,
+ VENDOR_REQUEST_MICROSOFT = 2
+};
+
+extern uint8_t const desc_ms_os_20[];
+extern const tusb_desc_webusb_url_t desc_webusb_url;
+
+static bool web_serial_connected = false;
+#endif
+
+
+
// Serial number as hex characters. This writes directly to the USB
// descriptor.
extern uint16_t usb_serial_number[1 + COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2];
@@ -141,6 +161,62 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
}
}
+#if CIRCUITPY_USB_VENDOR
+//--------------------------------------------------------------------+
+// WebUSB use vendor class
+//--------------------------------------------------------------------+
+
+bool tud_vendor_connected(void)
+{
+ return web_serial_connected;
+}
+
+// Invoked when a control transfer occurred on an interface of this class
+// Driver response accordingly to the request and the transfer stage (setup/data/ack)
+// return false to stall control endpoint (e.g unsupported request)
+bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
+{
+ // nothing to with DATA & ACK stage
+ if (stage != CONTROL_STAGE_SETUP ) return true;
+
+ switch (request->bRequest)
+ {
+ case VENDOR_REQUEST_WEBUSB:
+ // match vendor request in BOS descriptor
+ // Get landing page url
+ return tud_control_xfer(rhport, request, (void*) &desc_webusb_url, desc_webusb_url.bLength);
+
+ case VENDOR_REQUEST_MICROSOFT:
+ if ( request->wIndex == 7 )
+ {
+ // Get Microsoft OS 2.0 compatible descriptor
+ uint16_t total_len;
+ memcpy(&total_len, desc_ms_os_20+8, 2);
+
+ return tud_control_xfer(rhport, request, (void*) desc_ms_os_20, total_len);
+ } else
+ {
+ return false;
+ }
+
+ case 0x22:
+ // Webserial simulate the CDC_REQUEST_SET_CONTROL_LINE_STATE (0x22) to
+ // connect and disconnect.
+ web_serial_connected = (request->wValue != 0);
+
+ // response with status OK
+ return tud_control_status(rhport, request);
+
+ default:
+ // stall unknown request
+ return false;
+ }
+
+ return true;
+}
+#endif CIRCUITPY_USB_VENDOR
+
+
#if MICROPY_KBD_EXCEPTION
/**
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index a59e99e3d..70d3e146b 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -102,6 +102,11 @@ else
shared-module/usb_midi/PortOut.c
endif
+ ifeq ($(CIRCUITPY_USB_VENDOR), 1)
+ SRC_SUPERVISOR += \
+ lib/tinyusb/src/class/vendor/vendor_device.c
+ endif
+
CFLAGS += -DUSB_AVAILABLE
endif
@@ -119,6 +124,10 @@ ifndef USB_INTERFACE_NAME
USB_INTERFACE_NAME = "CircuitPython"
endif
+ifndef USB_WEBUSB_URL
+USB_WEBUSB_URL = "www.circuitpython.org"
+endif
+
USB_DEVICES_COMPUTED := CDC,MSC
ifeq ($(CIRCUITPY_USB_MIDI),1)
USB_DEVICES_COMPUTED := $(USB_DEVICES_COMPUTED),AUDIO
@@ -126,6 +135,9 @@ endif
ifeq ($(CIRCUITPY_USB_HID),1)
USB_DEVICES_COMPUTED := $(USB_DEVICES_COMPUTED),HID
endif
+ifeq ($(CIRCUITPY_USB_VENDOR),1)
+USB_DEVICES_COMPUTED := $(USB_DEVICES_COMPUTED),VENDOR
+endif
USB_DEVICES ?= "$(USB_DEVICES_COMPUTED)"
ifndef USB_HID_DEVICES
@@ -198,6 +210,12 @@ USB_DESCRIPTOR_ARGS = \
--output_c_file $(BUILD)/autogen_usb_descriptor.c\
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
+ifeq ($(CIRCUITPY_USB_VENDOR), 1)
+USB_DESCRIPTOR_ARGS += \
+ --vendor_ep_num_out 0 --vendor_ep_num_in 0 \
+ --webusb_url $(USB_WEBUSB_URL)
+endif
+
ifeq ($(USB_RENUMBER_ENDPOINTS), 0)
USB_DESCRIPTOR_ARGS += --no-renumber_endpoints
endif
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 0f936597f..86de86d1a 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -484,6 +484,7 @@ h_file = args.output_h_file
c_file.write("""\
#include <stdint.h>
+#include "tusb.h"
#include "py/objtuple.h"
#include "shared-bindings/usb_hid/Device.h"
#include "{H_FILE_NAME}"
@@ -628,11 +629,13 @@ extern const uint8_t hid_report_descriptor[{hid_report_descriptor_length}];
msc_vendor=args.manufacturer[:8],
msc_product=args.product[:16]))
-if 'VENDOR' in args.devices:
- h_file.write("""\
-extern const tusb_desc_webusb_url_t desc_webusb_url;
-
-""")
+# Currently getting compile-time errors in files like tusb_fifo.c
+# if we try do define this here (TODO figure this out!)
+#if 'VENDOR' in args.devices:
+# h_file.write("""\
+#extern const tusb_desc_webusb_url_t desc_webusb_url;
+#
+#""")
h_file.write("""\
#endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H
@@ -719,4 +722,44 @@ const tusb_desc_webusb_url_t desc_webusb_url =
.bScheme = 1, // 0: http, 1: https, 255: ""
.url = URL
}};
+
+// This next hardcoded descriptor was pulled from the usb_descriptor.c file of the
+// tinyusb webusb_serial demo. TODO - this is probably something else to integrate
+// into the adafruit_usb_descriptors project, especially with this next #define..
+#define ITF_NUM_VENDOR 6 // SWAG for now.
+
+#define MS_OS_20_DESC_LEN 0xB2
+
+uint8_t const desc_ms_os_20[] =
+{{
+ // Set header: length, type, windows version, total length
+ U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
+
+ // Configuration subset header: length, type, configuration index, reserved, configuration total length
+ U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A),
+
+ // Function Subset header: length, type, first interface, reserved, subset length
+ U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_NUM_VENDOR, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
+
+ // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
+ U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
+
+ // MS OS 2.0 Registry property descriptor: length, type
+ U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY),
+ U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
+ 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
+ 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
+ U16_TO_U8S_LE(0x0050), // wPropertyDataLength
+ //bPropertyData: “{{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}}”.
+ '{{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00,
+ '0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
+ '8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
+ '8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}}', 0x00, 0x00, 0x00, 0x00, 0x00
+}};
+
+TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size");
+
+// End of section about desc_ms_os_20
+
""".format(webusb_url=args.webusb_url))