summaryrefslogtreecommitdiff
path: root/supervisor
diff options
context:
space:
mode:
authorDan Halbert <halbert@adafruit.com>2021-02-05 09:11:43 -0500
committerGitHub <noreply@github.com>2021-02-05 09:11:43 -0500
commit0a55cfbde80e07679ded193e85ee118c1561fc63 (patch)
tree35340e49b9a40368626b5a907b6a9ff3b658bb37 /supervisor
parentf6e881e820e90bbc9adfc9a6cf0227c08ac41894 (diff)
parent1352938504539a649b185ca6b504e85e3d0203d7 (diff)
Merge pull request #4126 from FiriaCTO/webusb
WebUSB serial support (compile-time option, currently defaulted to OFF)
Diffstat (limited to 'supervisor')
-rw-r--r--supervisor/shared/serial.c30
-rw-r--r--supervisor/shared/usb/tusb_config.h1
-rw-r--r--supervisor/shared/usb/usb.c69
-rw-r--r--supervisor/supervisor.mk20
4 files changed, 120 insertions, 0 deletions
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 07c6aee6c..06b9e0c4e 100644
--- a/supervisor/shared/usb/usb.c
+++ b/supervisor/shared/usb/usb.c
@@ -37,6 +37,19 @@
#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.
+
+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];
@@ -145,6 +158,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..f559e004e 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,12 @@ ifndef USB_INTERFACE_NAME
USB_INTERFACE_NAME = "CircuitPython"
endif
+# In the following URL, don't include the https:// prefix.
+# It gets added automatically.
+ifndef USB_WEBUSB_URL
+USB_WEBUSB_URL = "circuitpython.org"
+endif
+
USB_DEVICES_COMPUTED := CDC,MSC
ifeq ($(CIRCUITPY_USB_MIDI),1)
USB_DEVICES_COMPUTED := $(USB_DEVICES_COMPUTED),AUDIO
@@ -126,6 +137,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 +212,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