From fbfb7b68cce3fbcccc423c1013c0c3cabe6a89d0 Mon Sep 17 00:00:00 2001 From: Kevin Banks Date: Mon, 25 Jan 2021 20:37:58 -0600 Subject: Most of the code we need has been pulled in from the tinyusb webusb_serial demo. Still LOTS to do regarding descriptors. --- supervisor/shared/serial.c | 30 +++++++++++++++ supervisor/shared/usb/tusb_config.h | 1 + supervisor/shared/usb/usb.c | 76 +++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) (limited to 'supervisor/shared') 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 /** -- cgit v1.2.3 From 1b031508e14a3cdfa2ba9c5cf158126d3f002cba Mon Sep 17 00:00:00 2001 From: Kevin Banks Date: Tue, 26 Jan 2021 20:43:19 -0600 Subject: BOS and MS_OS_2.0 descriptors have been added. Still more descriptor work TODO. --- supervisor/shared/usb/usb.c | 7 ----- tools/gen_usb_descriptor.py | 74 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 19 deletions(-) (limited to 'supervisor/shared') diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index 9b0cba8da..5db90d2fa 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -43,13 +43,6 @@ // 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; diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py index 86de86d1a..210ca1923 100644 --- a/tools/gen_usb_descriptor.py +++ b/tools/gen_usb_descriptor.py @@ -629,13 +629,21 @@ extern const uint8_t hid_report_descriptor[{hid_report_descriptor_length}]; msc_vendor=args.manufacturer[:8], msc_product=args.product[:16])) -# 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; -# -#""") +if 'VENDOR' in args.devices: + h_file.write("""\ +enum +{ + VENDOR_REQUEST_WEBUSB = 1, + VENDOR_REQUEST_MICROSOFT = 2 +}; + +extern uint8_t const desc_ms_os_20[]; + +// Currently getting compile-time errors in files like tusb_fifo.c +// if we try do define this here (TODO figure this out!) +//extern const tusb_desc_webusb_url_t desc_webusb_url; + +""") h_file.write("""\ #endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H @@ -711,7 +719,7 @@ c_file.write("""\ """) if 'VENDOR' in args.devices: - # Mimic what the tinyusb webusb demo does + # Mimic what the tinyusb webusb demo does in it's main.c file c_file.write(""" #define URL "{webusb_url}" @@ -723,13 +731,55 @@ const tusb_desc_webusb_url_t desc_webusb_url = .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. +// These next two hardcoded descriptor were 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.. + +// SWAG for now. Will have to be manually corrected until generated by gen_usb_descriptor.py +#define ITF_NUM_VENDOR 6i + +//--------------------------------------------------------------------+ +// BOS Descriptor +//--------------------------------------------------------------------+ + +/* Microsoft OS 2.0 registry property descriptor +Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx +device should create DeviceInterfaceGUIDs. It can be done by driver and +in case of real PnP solution device should expose MS "Microsoft OS 2.0 +registry property descriptor". Such descriptor can insert any record +into Windows registry per device/configuration/interface. In our case it +will insert "DeviceInterfaceGUIDs" multistring property. + +GUID is freshly generated and should be OK to use. + +https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/ +(Section Microsoft OS compatibility descriptors) +*/ + +#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) #define MS_OS_20_DESC_LEN 0xB2 +// BOS Descriptor is required for webUSB +uint8_t const desc_bos[] = +{{ + // total length, number of device caps + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), + + // Vendor Code, iLandingPage + TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), + + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) +}}; + +uint8_t const * tud_descriptor_bos_cb(void) +{{ + return desc_bos; +}} + + uint8_t const desc_ms_os_20[] = {{ // Set header: length, type, windows version, total length -- cgit v1.2.3 From e699a598905c95eb8249e89e436030376a518239 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Feb 2021 11:01:33 +0700 Subject: hack to fix 3986 just a proof to show that issue analysis is correct --- supervisor/shared/background_callback.c | 8 ++++++-- supervisor/shared/usb/usb.c | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'supervisor/shared') diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 288c9a4df..44709b60b 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -33,7 +33,7 @@ #include "supervisor/shared/tick.h" #include "shared-bindings/microcontroller/__init__.h" -STATIC volatile background_callback_t *callback_head, *callback_tail; +STATIC volatile background_callback_t * volatile callback_head, * volatile callback_tail; #define CALLBACK_CRITICAL_BEGIN (common_hal_mcu_disable_interrupts()) #define CALLBACK_CRITICAL_END (common_hal_mcu_enable_interrupts()) @@ -50,7 +50,6 @@ void background_callback_add_core(background_callback_t *cb) { cb->prev = (background_callback_t*)callback_tail; if (callback_tail) { callback_tail->next = cb; - cb->prev = (background_callback_t*)callback_tail; } if (!callback_head) { callback_head = cb; @@ -106,6 +105,9 @@ void background_callback_end_critical_section() { CALLBACK_CRITICAL_END; } +extern background_callback_t usb_callback; +extern void usb_background_do(void* unused); + void background_callback_reset() { CALLBACK_CRITICAL_BEGIN; background_callback_t *cb = (background_callback_t*)callback_head; @@ -118,6 +120,8 @@ void background_callback_reset() { callback_tail = NULL; in_background_callback = false; CALLBACK_CRITICAL_END; + + background_callback_add(&usb_callback, usb_background_do, NULL); } void background_callback_gc_collect(void) { diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index 07c6aee6c..af34f2598 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -93,13 +93,13 @@ void usb_background(void) { } } -static background_callback_t usb_callback; -static void usb_background_do(void* unused) { +/*static*/ background_callback_t usb_callback; +/*static*/ void usb_background_do(void* unused) { usb_background(); } void usb_irq_handler(void) { - tud_int_handler(0); + tud_int_handler(0); \ background_callback_add(&usb_callback, usb_background_do, NULL); } -- cgit v1.2.3 From 8d7b1f9e8c9545468305443ae6cae3d653ead8d2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Feb 2021 16:00:14 +0700 Subject: add usb_background_schedule() unconditionally schedule usb background after background_callback_reset() --- main.c | 1 + supervisor/shared/background_callback.c | 5 ----- supervisor/shared/usb/usb.c | 13 +++++++++---- supervisor/usb.h | 3 +++ 4 files changed, 13 insertions(+), 9 deletions(-) (limited to 'supervisor/shared') diff --git a/main.c b/main.c index d9cdcca1d..f85109e2f 100755 --- a/main.c +++ b/main.c @@ -184,6 +184,7 @@ STATIC void stop_mp(void) { #endif background_callback_reset(); + usb_background_schedule(); gc_deinit(); } diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 44709b60b..68a0a9667 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -105,9 +105,6 @@ void background_callback_end_critical_section() { CALLBACK_CRITICAL_END; } -extern background_callback_t usb_callback; -extern void usb_background_do(void* unused); - void background_callback_reset() { CALLBACK_CRITICAL_BEGIN; background_callback_t *cb = (background_callback_t*)callback_head; @@ -120,8 +117,6 @@ void background_callback_reset() { callback_tail = NULL; in_background_callback = false; CALLBACK_CRITICAL_END; - - background_callback_add(&usb_callback, usb_background_do, NULL); } void background_callback_gc_collect(void) { diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index af34f2598..9cbb295c8 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -93,16 +93,21 @@ void usb_background(void) { } } -/*static*/ background_callback_t usb_callback; -/*static*/ void usb_background_do(void* unused) { +static background_callback_t usb_callback; +static void usb_background_do(void* unused) { usb_background(); } -void usb_irq_handler(void) { - tud_int_handler(0); \ +void usb_background_schedule(void) +{ background_callback_add(&usb_callback, usb_background_do, NULL); } +void usb_irq_handler(void) { + tud_int_handler(0); + usb_background_schedule(); +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ diff --git a/supervisor/usb.h b/supervisor/usb.h index ccb35470c..1c709926a 100644 --- a/supervisor/usb.h +++ b/supervisor/usb.h @@ -35,6 +35,9 @@ // it may be necessary to call it directly. void usb_background(void); +// Schedule usb background +void usb_background_schedule(void); + // Ports must call this from their particular USB IRQ handler void usb_irq_handler(void); -- cgit v1.2.3