diff --git a/.gitignore b/.gitignore index 772f5d8ee..ea08146b4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ latex *.elf *.ind .env -/examples/*/*/build-* +/examples/*/*/build* test_old/ tests_obsolete/ _build diff --git a/changelog.md b/changelog.md index e25e93721..807b4dc3a 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,7 @@ ### Breaking -- TinyUSB does not directly implement USB IRQ Handler function anymore. Application must implement IRQ Handler and invoke `tud_irq_handler(rhport)`. This is due to: +- TinyUSB does not directly implement USB IRQ Handler function anymore. Application must implement IRQ Handler and invoke `tud_int_handler(rhport)`. This is due to: - IRQ Handler name can be different across system depending on the startup - Some OS need to execute enterISR()/exitISR() to work properly, also tracing tool may need to insert trace ISR enter/exit to record usb event @@ -12,7 +12,7 @@ ### MCU -- All default IRQ Handler is renamed to `dcd_irq_handler()` +- All default IRQ Handler is renamed to `dcd_int_handler()` ## 0.6.0 - 2019.03.30 diff --git a/docs/porting.md b/docs/porting.md index f80245014..fabf24510 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -68,7 +68,7 @@ This function should leave an internal D+/D- pull-up in its default power-on sta Enables or disables the USB device interrupt(s). May be used to prevent concurrency issues when mutating data structures shared between main code and the interrupt handler. -##### dcd_irq_handler +##### dcd_int_handler Processes all the hardware generated events e.g Bus reset, new data packet from host etc ... It will be called by application in the MCU USB interrupt handler. @@ -134,6 +134,14 @@ Opening an endpoint is done for all non-control endpoints once the host picks a Also make sure to enable endpoint specific interrupts. +##### dcd_edpt_close + +Close an endpoint. his function is used for implementing alternate settings. + +After calling this, the device should not respond to any packets directed towards this endpoint. When called, this function must abort any transfers in progress through this endpoint, before returning. + +Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call. + ##### dcd_edpt_xfer `dcd_edpt_xfer` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral. diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 66d8571cf..b65575ce6 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -13,6 +13,6 @@ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # This can cause some TinyUSB API missing, this hack to allow us to fill those API # to pass the compilation process CFLAGS += \ - -D"tud_irq_handler(x)= " \ + -D"tud_int_handler(x)= " \ include ../../rules.mk diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 9783bd4f6..3536702bb 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 733fd2d0a..09e98b247 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 525019aaa..794e996b6 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_FREERTOS diff --git a/examples/device/dfu_rt/src/main.h b/examples/device/dfu_rt/src/main.h deleted file mode 100644 index 673247ec7..000000000 --- a/examples/device/dfu_rt/src/main.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H -void led_indicator_pulse(void); - -#endif diff --git a/examples/device/dfu_rt/src/tusb_config.h b/examples/device/dfu_rt/src/tusb_config.h index d1efcdab5..f6bf79e05 100644 --- a/examples/device/dfu_rt/src/tusb_config.h +++ b/examples/device/dfu_rt/src/tusb_config.h @@ -21,10 +21,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index 5cd661b2b..3d900efd9 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -77,92 +77,25 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ -#if CFG_TUD_HID - -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) -}; - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void) -{ - return desc_hid_report; -} - -#endif - //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ enum { -#if CFG_TUD_CDC - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, -#endif - -#if CFG_TUD_MSC - ITF_NUM_MSC, -#endif - -#if CFG_TUD_HID - ITF_NUM_HID, -#endif - -#if CFG_TUD_DFU_RT ITF_NUM_DFU_RT, -#endif - ITF_NUM_TOTAL }; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + \ - CFG_TUD_HID*TUD_HID_DESC_LEN + (CFG_TUD_DFU_RT)*TUD_DFU_RT_DESC_LEN) - -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force - // endpoint number for MSC to 5 - #define EPNUM_MSC 0x05 -#else - #define EPNUM_MSC 0x03 -#endif - +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_RT_DESC_LEN) uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), -#if CFG_TUD_CDC - // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), -#endif - -#if CFG_TUD_MSC - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), -#endif - -#if CFG_TUD_HID - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10), -#endif - -#if CFG_TUD_DFU_RT // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 7, 0x0d, 1000, 4096), -#endif + TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 4, 0x0d, 1000, 4096), }; diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 6d2fd0836..adc795cc2 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 2debafd2a..4dc3ecea4 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 56f326f31..8dd7ef9fe 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 82d07c60a..841a8aa00 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 38f10919b..b672ca3bb 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,13 +26,9 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a CDC-ECM, RNDIS, or CDC-EEM USB virtual network adapter +this appears as either a RNDIS or CDC-ECM USB virtual network adapter; the OS picks its preference -CDC-ECM should be valid on Linux and MacOS hosts -RNDIS should be valid on Linux and Windows hosts -CDC-EEM should be valid on Linux hosts - -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network adapters to emulate. +RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and macOS hosts The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 0b40fefab..45c0b8ac1 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE @@ -79,9 +80,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -//#define CFG_TUD_NET OPT_NET_ECM -#define CFG_TUD_NET OPT_NET_RNDIS -//#define CFG_TUD_NET OPT_NET_EEM +#define CFG_TUD_NET 1 #ifdef __cplusplus } diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index 6ce36cfef..51af11e8b 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -24,13 +24,12 @@ */ #include "tusb.h" -#include "usb_descriptors.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. * * Auto ProductID layout's Bitmap: - * [MSB] NET1:NET0 | VENDOR | MIDI | HID | MSC | CDC [LSB] + * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ @@ -47,6 +46,20 @@ enum STRID_MAC }; +enum +{ + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_TOTAL +}; + +enum +{ + CONFIG_ID_RNDIS = 0, + CONFIG_ID_ECM = 1, + CONFIG_ID_COUNT +}; + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ @@ -56,20 +69,22 @@ tusb_desc_device_t const desc_device = .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_UNSPECIFIED, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, + // Use Interface Association Descriptor (IAD) device class + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, - .bcdDevice = 0x0100, + .bcdDevice = 0x0101, .iManufacturer = STRID_MANUFACTURER, .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, - .bNumConfigurations = 0x01 + .bNumConfigurations = CONFIG_ID_COUNT // multiple configurations }; // Invoked when received GET DEVICE DESCRIPTOR @@ -82,20 +97,8 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -enum -{ - ITF_NUM_CDC = 0, - ITF_NUM_CDC_DATA, - ITF_NUM_TOTAL -}; - -#if CFG_TUD_NET == OPT_NET_ECM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) -#elif CFG_TUD_NET == OPT_NET_EEM - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) -#endif +#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -105,21 +108,33 @@ enum #define EPNUM_CDC 2 #endif -uint8_t const desc_configuration[] = +static uint8_t const rndis_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + // Config number (index+1), interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if CFG_TUD_NET == OPT_NET_ECM - // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), -#elif CFG_TUD_NET == OPT_NET_RNDIS // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#elif CFG_TUD_NET == OPT_NET_EEM - // Interface number, description string index, EP data address (out, in) and size. - TUD_CDC_EEM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), -#endif +}; + +static uint8_t const ecm_configuration[] = +{ + // Config number (index+1), interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), + + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, 0x81, 64, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +}; + +// Configuration array: RNDIS and CDC-ECM +// - Windows only works with RNDIS +// - MacOS only works with CDC-ECM +// - Linux will work on both +// Note index is Num-1x +static uint8_t const * const configuration_arr[2] = +{ + [CONFIG_ID_RNDIS] = rndis_configuration, + [CONFIG_ID_ECM ] = ecm_configuration }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -127,8 +142,7 @@ uint8_t const desc_configuration[] = // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { - (void) index; // for multiple configurations - return desc_configuration; + return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL; } //--------------------------------------------------------------------+ @@ -141,8 +155,8 @@ static char const* string_desc_arr [] = [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer [STRID_PRODUCT] = "TinyUSB Device", // Product - [STRID_SERIAL] = "123456", // Serials - [STRID_INTERFACE] = "TinyUSB Network Interface" // CDC-ECM Interface + [STRID_SERIAL] = "123456", // Serial + [STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description // STRID_MAC index is handled separately }; diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.h b/examples/device/net_lwip_webserver/src/usb_descriptors.h deleted file mode 100644 index 280570831..000000000 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef USB_DESCRIPTORS_H_ -#define USB_DESCRIPTORS_H_ - -#endif /* USB_DESCRIPTORS_H_ */ diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index b6a40355e..1022125bb 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -21,12 +21,12 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif - #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index b3f449f93..e7e0b81bc 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -39,10 +39,11 @@ #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif #define CFG_TUSB_OS OPT_OS_NONE diff --git a/hw/bsp/adafruit_clue/adafruit_clue.c b/hw/bsp/adafruit_clue/adafruit_clue.c index 54b822fc9..cb5c2f223 100644 --- a/hw/bsp/adafruit_clue/adafruit_clue.c +++ b/hw/bsp/adafruit_clue/adafruit_clue.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c index a3ab49a5d..d2d126311 100644 --- a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c +++ b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c index 17e619704..9638b3cc8 100644 --- a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c +++ b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index 0e2583383..4ff95b2ff 100644 --- a/hw/bsp/circuitplayground_express/circuitplayground_express.c +++ b/hw/bsp/circuitplayground_express/circuitplayground_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 756c9d384..7fc047490 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -37,7 +37,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 87b19260e..87f1e83cc 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -240,7 +240,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -251,7 +251,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/hw/bsp/feather_m0_express/feather_m0_express.c b/hw/bsp/feather_m0_express/feather_m0_express.c index 83b20793e..4eb157c8f 100644 --- a/hw/bsp/feather_m0_express/feather_m0_express.c +++ b/hw/bsp/feather_m0_express/feather_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m4_express/feather_m4_express.c b/hw/bsp/feather_m4_express/feather_m4_express.c index 8b4764cd0..72183c612 100644 --- a/hw/bsp/feather_m4_express/feather_m4_express.c +++ b/hw/bsp/feather_m4_express/feather_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_1_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_2_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_3_Handler (void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index e36615ee1..34e7fa8ec 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c index fb4ef9af2..284ae27b1 100644 --- a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c +++ b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_stm32f405/feather_stm32f405.c b/hw/bsp/feather_stm32f405/feather_stm32f405.c index bdd216272..a8c782da5 100644 --- a/hw/bsp/feather_stm32f405/feather_stm32f405.c +++ b/hw/bsp/feather_stm32f405/feather_stm32f405.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/fomu/board.mk b/hw/bsp/fomu/board.mk index ffd0158c9..70fb66975 100644 --- a/hw/bsp/fomu/board.mk +++ b/hw/bsp/fomu/board.mk @@ -14,7 +14,7 @@ BSP_DIR = hw/bsp/fomu # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/fomu.ld -SRC_S += hw/bsp/fomu/crt0-vexriscv.S +SRC_S += hw/bsp/$(BOARD)/crt0-vexriscv.S INC += \ $(TOP)/$(BSP_DIR)/include @@ -27,5 +27,9 @@ CHIP_FAMILY = eptri FREERTOS_PORT = RISC-V # flash using dfu-util +$(BUILD)/$(BOARD)-firmware.dfu: $(BUILD)/$(BOARD)-firmware.bin + @echo "Create $@" + python $(TOP)/hw/bsp/$(BOARD)/dfu.py -b $^ -D 0x1209:0x5bf0 $@ + flash: $(BUILD)/$(BOARD)-firmware.dfu dfu-util -D $^ diff --git a/hw/bsp/fomu/dfu.py b/hw/bsp/fomu/dfu.py new file mode 100644 index 000000000..32479350c --- /dev/null +++ b/hw/bsp/fomu/dfu.py @@ -0,0 +1,95 @@ +#!/usr/bin/python + +# Written by Antonio Galea - 2010/11/18 +# Updated for DFU 1.1 by Sean Cross - 2020/03/31 +# Distributed under Gnu LGPL 3.0 +# see http://www.gnu.org/licenses/lgpl-3.0.txt + +import sys,struct,zlib,os +from optparse import OptionParser + +DEFAULT_DEVICE="0x1209:0x5bf0" + +def named(tuple,names): + return dict(zip(names.split(),tuple)) +def consume(fmt,data,names): + n = struct.calcsize(fmt) + return named(struct.unpack(fmt,data[:n]),names),data[n:] +def cstring(string): + return string.split('\0',1)[0] +def compute_crc(data): + return 0xFFFFFFFF & -zlib.crc32(data) -1 + +def parse(file,dump_images=False): + print ('File: "%s"' % file) + data = open(file,'rb').read() + crc = compute_crc(data[:-4]) + data = data[len(data)-16:] + suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') + print ('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) + if crc != suffix['crc']: + print ("CRC ERROR: computed crc32 is 0x%08x" % crc) + data = data[16:] + if data: + print ("PARSE ERROR") + +def build(file,data,device=DEFAULT_DEVICE): + # Parse the VID and PID from the `device` argument + v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) + + # Generate the DFU suffix, consisting of these fields: + # Field name | Length | Description + # ================+=========+================================ + # bcdDevice | 2 | The release number of this firmware (0xffff - don't care) + # idProduct | 2 | PID of this device + # idVendor | 2 | VID of this device + # bcdDFU | 2 | Version of this DFU spec (0x01 0x00) + # ucDfuSignature | 3 | The characters 'DFU', printed in reverse order + # bLength | 1 | The length of this suffix (16 bytes) + # dwCRC | 4 | A CRC32 of the data, including this suffix + data += struct.pack('<4H3sB',0xffff,d,v,0x0100,b'UFD',16) + crc = compute_crc(data) + # Append the CRC32 of the entire block + data += struct.pack('bInterfaceSubClass); + TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - // Only support AT commands, no protocol and vendor specific commands. - TU_ASSERT(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - itf_desc->bInterfaceProtocol == 0xff); + // Note: 0xFF can be used with RNDIS + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); // Find available interface cdcd_interface_t * p_cdc = NULL; @@ -262,12 +262,12 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 595e7fd62..5e45e8f6b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -86,7 +86,7 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate return tuh_cdc_mounted(dev_addr) && - (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) && + (CDC_COMM_PROTOCOL_NONE <= cdch_data[dev_addr-1].itf_protocol) && (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index ad1871dad..0ef5fe63f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -61,8 +61,8 @@ bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 (void) rhport; // Ensure this is DFU Runtime - TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); - TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); + TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 4348a0f3a..294d993e3 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -58,7 +58,7 @@ typedef enum //--------------------------------------------------------------------+ // Invoked when received new data -TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); +TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7cb35f1ce..cbdc5bece 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -160,6 +160,8 @@ void hidd_reset(uint8_t rhport) bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) { + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + uint8_t const *p_desc = (uint8_t const *) desc_itf; // Find available interface diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ae6e3afe1..6eb522380 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -253,21 +253,31 @@ void midid_reset(uint8_t rhport) } } -bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length) +bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length) { - // For now handle the audio control interface as well. - if ( AUDIO_SUBCLASS_CONTROL == p_interface_desc->bInterfaceSubClass) { - uint8_t const * p_desc = tu_desc_next ( (uint8_t const *) p_interface_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - // Skip over the class specific descriptor. - (*p_length) += tu_desc_len(p_desc); + // 1st Interface is Audio Control v1 + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol); + + uint16_t drv_len = tu_desc_len(desc_itf); + uint8_t const * p_desc = tu_desc_next(desc_itf); + + // Skip Class Specific descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - return true; } - TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == p_interface_desc->bInterfaceSubClass && - AUDIO_PROTOCOL_V1 == p_interface_desc->bInterfaceProtocol ); + // 2nd Interface is MIDI Streaming + TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; + + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol ); // Find available interface midid_interface_t * p_midi = NULL; @@ -280,13 +290,15 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, } } - p_midi->itf_num = p_interface_desc->bInterfaceNumber; + p_midi->itf_num = desc_midi->bInterfaceNumber; - uint8_t const * p_desc = tu_desc_next( (uint8_t const *) p_interface_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + // next descriptor + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + // Find and open endpoint descriptors uint8_t found_endpoints = 0; - while (found_endpoints < p_interface_desc->bNumEndpoints) + while (found_endpoints < desc_midi->bNumEndpoints) { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { @@ -298,14 +310,16 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, p_midi->ep_out = ep_addr; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += p_desc[DESC_OFFSET_LEN]; p_desc = tu_desc_next(p_desc); found_endpoints += 1; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += p_desc[DESC_OFFSET_LEN]; p_desc = tu_desc_next(p_desc); } + *p_length = drv_len; + // Prepare for incoming data TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 06cc9dbb6..68f5587fd 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -157,7 +157,8 @@ void mscd_reset(uint8_t rhport) bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) { // only support SCSI's BOT protocol - TU_ASSERT(MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && + TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && + MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); mscd_interface_t * p_msc = &_mscd_itf; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 68520625a..0f2ccbd44 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) ) +#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) #include "net_device.h" #include "device/usbd_pvt.h" @@ -40,40 +40,60 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_num; + uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface + uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active + uint8_t ep_notif; uint8_t ep_in; uint8_t ep_out; + + bool ecm_mode; + + // Endpoint descriptor use to open/close when receving SetInterface + // TODO since configuration descriptor may not be long-lived memory, we should + // keep a copy of endpoint attribute instead + uint8_t const * ecm_desc_epdata; + } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_ECM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 0 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL -#elif CFG_TUD_NET == OPT_NET_RNDIS - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 - #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS -#elif CFG_TUD_NET == OPT_NET_EEM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 - #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL -#endif +#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) +#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN]; -#if CFG_TUD_NET == OPT_NET_ECM - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static tusb_control_request_t notify = - { - .bmRequestType = 0x21, - .bRequest = 0 /* NETWORK_CONNECTION */, +struct ecm_notify_struct +{ + tusb_control_request_t header; + uint32_t downlink, uplink; +}; + +static const struct ecm_notify_struct ecm_notify_nc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */, .wValue = 1 /* Connected */, .wLength = 0, - }; -#elif CFG_TUD_NET == OPT_NET_RNDIS - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; -#endif + }, +}; + +static const struct ecm_notify_struct ecm_notify_csc = +{ + .header = { + .bmRequestType = 0xA1, + .bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */, + .wLength = 8, + }, + .downlink = 9728000, + .uplink = 9728000, +}; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +{ + uint8_t rndis_buf[120]; + struct ecm_notify_struct ecm_buf; +} notify; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -115,19 +135,28 @@ void netd_reset(uint8_t rhport) bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { - // sanity check the descriptor - TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass); + bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && + TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol); + + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); + + TU_VERIFY ( is_rndis || is_ecm ); // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); + TU_ASSERT(0 == _netd_itf.ep_notif); - //------------- first Interface -------------// + // sanity check the descriptor + _netd_itf.ecm_mode = is_ecm; + + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; - uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); + uint8_t const * p_desc = tu_desc_next( itf_desc ); -#if CFG_TUD_NET != OPT_NET_EEM // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) { @@ -142,35 +171,49 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - //------------- second Interface -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { - // next to endpoint descriptor - p_desc = tu_desc_next(p_desc); - (*p_length) += sizeof(tusb_desc_interface_t); - } -#endif + //------------- Data Interface -------------// + // - RNDIS Data followed immediately by a pair of endpoints + // - CDC-ECM data interface has 2 alternate settings + // - 0 : zero endpoints for inactive (default) + // - 1 : IN & OUT endpoints for active networking + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); - if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + do { - // Open endpoint pair + tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc; + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass); + + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + }while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) ); + + // Pair of endpoints + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + + if ( _netd_itf.ecm_mode ) + { + // ECM by default is in-active, save the endpoint attribute + // to open later when received setInterface + _netd_itf.ecm_desc_epdata = p_desc; + }else + { + // Open endpoint pair for RNDIS TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); - (*p_length) += 2*sizeof(tusb_desc_endpoint_t); + tud_network_init_cb(); + + // we are ready to transmit a packet + can_xmit = true; + + // prepare for incoming packets + tud_network_recv_renew(); } - tud_network_init_cb(); - - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); return true; } @@ -181,116 +224,167 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques { (void) rhport; - // Handle class request only - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - TU_VERIFY (_netd_itf.itf_num == request->wIndex); - -#if CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + // Handle RNDIS class control OUT only + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.direction == TUSB_DIR_OUT && + _netd_itf.itf_num == request->wIndex) { - rndis_class_set_handler(rndis_buf, request->wLength); + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } } -#endif return true; } +static void ecm_report(bool nc) +{ + notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; + notify.ecm_buf.header.wIndex = _netd_itf.itf_num; + netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); +} + // Handle class control request // return false to stall control endpoint (e.g unsupported request) bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) { - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) + { + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } + break; -#if CFG_TUD_NET == OPT_NET_ECM - /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ - if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) - { - tud_control_xfer(rhport, request, NULL, 0); - notify.wIndex = request->wIndex; - usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, (uint8_t *)¬ify, sizeof(notify)); + case TUSB_REQ_SET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; + + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); + + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); + + _netd_itf.itf_data_alt = req_alt; + + if ( _netd_itf.itf_data_alt ) + { + // TODO since we don't actually close endpoint + // hack here to not re-open it + if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 ) + { + TU_ASSERT(_netd_itf.ecm_desc_epdata); + TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); + + // TODO should be merge with RNDIS's after endpoint opened + // Also should have opposite callback for application to disable network !! + tud_network_init_cb(); + can_xmit = true; // we are ready to transmit a packet + tud_network_recv_renew(); // prepare for incoming packets + } + }else + { + // TODO close the endpoint pair + // For now pretend that we did, this should have no harm since host won't try to + // communicate with the endpoints again + // _netd_itf.ep_in = _netd_itf.ep_out = 0 + } + + tud_control_status(rhport, request); + } + break; + + // unsupported request + default: return false; + } + break; + + case TUSB_REQ_TYPE_CLASS: + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + + if (_netd_itf.ecm_mode) + { + /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ + if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) + { + tud_control_xfer(rhport, request, NULL, 0); + ecm_report(true); + } + } + else + { + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); + TU_ASSERT(msglen <= sizeof(notify.rndis_buf)); + tud_control_xfer(rhport, request, notify.rndis_buf, msglen); + } + else + { + tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + } + } + break; + + // unsupported request + default: return false; } -#elif CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf; - uint32_t msglen = tu_le32toh(rndis_msg->MessageLength); - TU_ASSERT(msglen <= sizeof(rndis_buf)); - tud_control_xfer(rhport, request, rndis_buf, msglen); - } - else - { - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); - } -#else - (void)rhport; -#endif return true; } -struct cdc_eem_packet_header -{ - uint16_t length:14; - uint16_t bmCRC:1; - uint16_t bmType:1; -}; - static void handle_incoming_packet(uint32_t len) { uint8_t *pnt = received; uint32_t size = 0; -#if CFG_TUD_NET == OPT_NET_ECM - size = len; -#elif CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; - if (len >= sizeof(rndis_data_packet_t)) - if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) - if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) - { - pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; - size = r->DataLength; - } -#elif CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; - - (void)len; - - if (hdr->bmType) + if (_netd_itf.ecm_mode) { - /* EEM Control Packet: discard it */ - tud_network_recv_renew(); + size = len; } else { - /* EEM Data Packet */ - pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; - size = hdr->length - 4; /* discard the unused CRC-32 */ + rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + if (len >= sizeof(rndis_data_packet_t)) + if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len)) + if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len) + { + pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)]; + size = r->DataLength; + } } -#endif + + bool accepted = false; if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - bool accepted = true; if (p) { memcpy(p->payload, pnt, size); p->len = size; accepted = tud_network_recv_cb(p); - } - if (!p || !accepted) - { - /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ - tud_network_recv_renew(); + if (!accepted) pbuf_free(p); } } + + if (!accepted) + { + /* if a buffer was never handled by user code, we must renew on the user's behalf */ + tud_network_recv_renew(); + } } bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -320,6 +414,11 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } + if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) + { + if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); + } + return true; } @@ -337,7 +436,7 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; - len = CFG_TUD_NET_PACKET_PREFIX_LEN; + len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -347,23 +446,15 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if CFG_TUD_NET == OPT_NET_RNDIS - rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; - memset(hdr, 0, sizeof(rndis_data_packet_t)); - hdr->MessageType = REMOTE_NDIS_PACKET_MSG; - hdr->MessageLength = len; - hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); - hdr->DataLength = len - sizeof(rndis_data_packet_t); -#elif CFG_TUD_NET == OPT_NET_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted; - /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */ - data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF; - /* adjust length to reflect added fake CRC-32 */ - len += 4; - hdr->bmType = 0; /* EEM Data Packet */ - hdr->length = len - sizeof(struct cdc_eem_packet_header); - hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */ -#endif + if (!_netd_itf.ecm_mode) + { + rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + memset(hdr, 0, sizeof(rndis_data_packet_t)); + hdr->MessageType = REMOTE_NDIS_PACKET_MSG; + hdr->MessageLength = len; + hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); + hdr->DataLength = len - sizeof(rndis_data_packet_t); + } do_in_xfer(transmitted, len); } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 92d8d34ef..abe26ced3 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -263,17 +263,19 @@ void usbtmcd_init_cb(void) bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { (void)rhport; - TU_ASSERT(usbtmc_state.state == STATE_CLOSED); uint8_t const * p_desc; uint8_t found_endpoints = 0; + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); + #ifndef NDEBUG - TU_ASSERT(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS); - TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS); // Only 2 or 3 endpoints are allowed for USBTMC. TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); #endif + TU_ASSERT(usbtmc_state.state == STATE_CLOSED); + // Interface (*p_length) = 0u; p_desc = (uint8_t const *) itf_desc; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8db5005f4..7f2fe9793 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -168,6 +168,8 @@ void vendord_reset(uint8_t rhport) bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) { + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass); + // Find available interface vendord_interface_t* p_vendor = NULL; for(uint8_t i=0; i= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + +typedef struct +{ + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif void (* init ) (void); void (* reset ) (uint8_t rhport); @@ -89,7 +98,7 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - .class_code = TUSB_CLASS_CDC, + DRIVER_NAME("CDC") .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, @@ -102,7 +111,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MSC { - .class_code = TUSB_CLASS_MSC, + DRIVER_NAME("MSC") .init = mscd_init, .reset = mscd_reset, .open = mscd_open, @@ -115,7 +124,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { - .class_code = TUSB_CLASS_HID, + DRIVER_NAME("HID") .init = hidd_init, .reset = hidd_reset, .open = hidd_open, @@ -128,7 +137,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MIDI { - .class_code = TUSB_CLASS_AUDIO, + DRIVER_NAME("MIDI") .init = midid_init, .open = midid_open, .reset = midid_reset, @@ -141,7 +150,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { - .class_code = TUSB_CLASS_VENDOR_SPECIFIC, + DRIVER_NAME("VENDOR") .init = vendord_init, .reset = vendord_reset, .open = vendord_open, @@ -153,12 +162,8 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_USBTMC - // Presently USBTMC is the only defined class with the APP_SPECIFIC class code. - // We maybe need to add subclass codes here, or a callback to ask if a driver can - // handle a particular interface. { - .class_code = TUD_USBTMC_APP_CLASS, - //.subclass_code = TUD_USBTMC_APP_SUBCLASS + DRIVER_NAME("TMC") .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, @@ -171,8 +176,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RT { - .class_code = TUD_DFU_APP_CLASS, - //.subclass_code = TUD_DFU_APP_SUBCLASS + DRIVER_NAME("DFU-RT") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, @@ -185,19 +189,14 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET { - .class_code = -#if CFG_TUD_NET == OPT_NET_RNDIS - TUD_RNDIS_ITF_CLASS, -#else - TUSB_CLASS_CDC, -#endif + DRIVER_NAME("NET") .init = netd_init, .reset = netd_reset, .open = netd_open, .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, - .sof = NULL + .sof = NULL, }, #endif }; @@ -244,32 +243,6 @@ static char const* const _usbd_event_str[DCD_EVENT_COUNT] = "FUNC_CALL" }; -// must be same driver order as usbd_class_drivers[] -static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = -{ - #if CFG_TUD_CDC - "CDC", - #endif - #if CFG_TUD_MSC - "MSC", - #endif - #if CFG_TUD_HID - "HID", - #endif - #if CFG_TUD_MIDI - "MIDI", - #endif - #if CFG_TUD_VENDOR - "Vendor", - #endif - #if CFG_TUD_USBTMC - "USBTMC" - #endif - #if CFG_TUD_NET - "NET" - #endif -}; - static char const* const _tusb_std_request_str[] = { "Get Status" , @@ -326,7 +299,7 @@ bool tud_init (void) // Init class drivers for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { - TU_LOG2("%s init\r\n", _usbd_driver_str[i]); + TU_LOG2("%s init\r\n", _usbd_driver[i].name); _usbd_driver[i].init(); } @@ -435,7 +408,7 @@ void tud_task (void) uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir]; TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); - TU_LOG2(" %s xfer callback\r\n", _usbd_driver_str[drv_id]); + TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name); _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } @@ -480,7 +453,7 @@ static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_req TU_ASSERT(_usbd_driver[drvid].control_request); usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); - TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]); + TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); return _usbd_driver[drvid].control_request(rhport, request); } @@ -596,38 +569,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const drvid = _usbd_dev.itf2drv[itf]; TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + // all requests to Interface (STD or Class) is forwarded to class driver. + // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE + if ( !invoke_class_control(rhport, drvid, p_request) ) { - switch ( p_request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: - { - // TODO not support alternate interface yet - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - } - break; + // For GET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings. + TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && + TUSB_REQ_GET_INTERFACE == p_request->bRequest); - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const alternate = (uint8_t) p_request->wValue; - - // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); - tud_control_status(rhport, p_request); - } - break; - - default: - // forward to class driver: "STD request to Interface" - // GET HID REPORT DESCRIPTOR falls into this case - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); - break; - } - }else - { - // forward to class driver: "non-STD request to Interface" - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); } } break; @@ -727,37 +679,59 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - // Each interface always starts with Interface or Association descriptor + tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + + // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = tu_desc_next(p_desc); // ignore Interface Association - }else - { - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - - tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; - - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) - { - if ( _usbd_driver[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); - - // Interface number must not be used already TODO alternate interface - TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - uint16_t itf_len=0; - TU_LOG2(" %s open\r\n", _usbd_driver_str[drv_id]); - TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); - - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); - - p_desc += itf_len; // next interface + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface } + + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); + + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint8_t drv_id; + uint16_t drv_len; + + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) + { + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + + TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If IAD exist, assign all interfaces to the same driver + if (desc_itf_assoc) + { + // IAD's first interface number and class/subclass/protocol should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass && + desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass && + desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } + } + + break; + } + } + + // Assert if cannot find supported driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + + p_desc += drv_len; // next interface } // invoke callback @@ -1035,4 +1009,20 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) return _usbd_dev.ep_status[epnum][dir].stalled; } +/** + * usbd_edpt_close will disable an endpoint. + * + * In progress transfers on this EP may be delivered after this call. + * + */ +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + TU_ASSERT(dcd_edpt_close, /**/); + TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); + + dcd_edpt_close(rhport, ep_addr); + + return; +} + #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 6b31d8113..fcb4e5c5f 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -48,7 +48,7 @@ bool tud_init (void); void tud_task (void); // Interrupt handler, name alias to DCD -#define tud_irq_handler dcd_irq_handler +#define tud_int_handler dcd_int_handler // Check if device is connected and configured bool tud_mounted(void); @@ -183,9 +183,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ /* Interface Associate */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, 0,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\ /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\ /* CDC Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC Call */\ @@ -291,23 +291,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID, // bulk-in endpoint ID #define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \ -/* Interface */ \ + /* Interface */ \ 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx #define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u #define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \ -/* Endpoint Out */ \ -7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ -/* Endpoint In */ \ -7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u + /* Endpoint Out */ \ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \ + /* Endpoint In */ \ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u #define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u) /* optional interrupt endpoint */ \ // _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number? #define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \ -7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 + 7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16 #define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u) @@ -342,12 +342,14 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// -// Length of template descriptor: 62 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7) +// Length of template descriptor: 71 bytes +#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7) // CDC-ECM Descriptor Template // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. #define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ @@ -358,8 +360,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\ /* Endpoint Notification */\ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (default inactive) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* CDC Data Interface (alternative active) */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ /* Endpoint In */\ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ /* Endpoint Out */\ @@ -372,10 +376,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Windows XP */ #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL - #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS + #define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else /* Windows 7+ */ - #define TUD_RNDIS_ITF_CLASS 0xE0 + #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER #define TUD_RNDIS_ITF_SUBCLASS 0x01 #define TUD_RNDIS_ITF_PROTOCOL 0x03 #endif @@ -408,22 +412,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 -//------------- CDC-EEM -------------// - -// Length of template descriptor: 23 bytes -#define TUD_CDC_EEM_DESC_LEN (9+7+7) - -// CDC-EEM Descriptor Template -// Interface number, description string index, EP data address (out, in) and size. -#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* EEM Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 - - #ifdef __cplusplus } #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index b9947044b..26b9700e8 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -38,6 +38,7 @@ //--------------------------------------------------------------------+ //bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 126f3ea20..986df3b3b 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -190,9 +190,6 @@ void dcd_init(uint8_t rhport) USB_ENUMDONEMSK_M | USB_RESETDETMSK_M | USB_DISCONNINTMSK_M; - - ESP_LOGV(TAG, "DCD init - Soft CONNECT"); - USB0.dctl &= ~USB_SFTDISCON_M; // Connect } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -216,18 +213,20 @@ void dcd_remote_wakeup(uint8_t rhport) (void)rhport; } -// disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - USB0.dctl |= USB_SFTDISCON_M; -} - // connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { + (void) rhport; USB0.dctl &= ~USB_SFTDISCON_M; } +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB0.dctl |= USB_SFTDISCON_M; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ @@ -639,7 +638,7 @@ static void handle_epin_ints(void) } -static void dcd_int_handler(void* arg) +static void _dcd_int_handler(void* arg) { (void) arg; @@ -727,7 +726,7 @@ static void dcd_int_handler(void* arg) void dcd_int_enable (uint8_t rhport) { (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) dcd_int_handler, NULL, &usb_ih); + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); } void dcd_int_disable (uint8_t rhport) diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 2c01f8017..bd61df86a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -331,7 +331,7 @@ void maybe_transfer_complete(void) { } -void dcd_irq_handler (uint8_t rhport) +void dcd_int_handler (uint8_t rhport) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 93d9029d6..7703ee0dc 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -138,9 +138,6 @@ void dcd_init (uint8_t rhport) (void) rhport; tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); - - // Enable pull-up, disable transceiver - UDP->UDP_TXVC = UDP_TXVC_PUON | UDP_TXVC_TXVDIS_Msk; } // Enable device interrupt @@ -186,6 +183,23 @@ void dcd_remote_wakeup (uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + + // Enable pull-up, disable transceiver + UDP->UDP_TXVC = UDP_TXVC_PUON | UDP_TXVC_TXVDIS_Msk; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + + // disable both pullup and transceiver + UDP->UDP_TXVC = UDP_TXVC_TXVDIS_Msk; +} + + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -333,7 +347,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { uint32_t const intr_mask = UDP->UDP_IMR; uint32_t const intr_status = UDP->UDP_ISR & intr_mask; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 389266217..95240f9f0 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -373,7 +373,7 @@ void bus_reset(void) _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 050aea255..9195b8dbe 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -306,7 +306,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index df72cbb2d..edd1e14a7 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -312,7 +312,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 3baed87c5..aceb6df09 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -112,8 +112,6 @@ static struct uint16_t total_bytes; } ctrl_in_xfer; -static volatile bool configuration_changed; - static volatile struct xfer_ctl_t *current_dma_xfer; @@ -219,7 +217,6 @@ static void bus_reset(void) /* Reset USB device address */ USBD->FADDR = 0; - configuration_changed = false; current_dma_xfer = NULL; } @@ -305,7 +302,6 @@ void dcd_set_config(uint8_t rhport, uint8_t config_num) { (void) rhport; (void) config_num; - configuration_changed = true; } void dcd_remote_wakeup(uint8_t rhport) @@ -435,7 +431,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) } } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; @@ -579,15 +575,14 @@ void dcd_irq_handler(uint8_t rhport) else if (cep_state & USBD_CEPINTSTS_STSDONEIF_Msk) { /* given ACK from host has happened, we can now set the address (if not already done) */ - if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) USBD->FADDR = assigned_address; - - if (configuration_changed) + if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) { + USBD->FADDR = assigned_address; + for (enum ep_enum ep_index = PERIPH_EPA; ep_index < PERIPH_MAX_EP; ep_index++) { if (USBD->EP[ep_index].EPCFG & USBD_EPCFG_EPEN_Msk) USBD->EP[ep_index].EPRSPCTL = USBD_EPRSPCTL_TOGGLE_Msk; } - configuration_changed = false; } USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 1d755ce63..21a678c66 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -181,9 +181,7 @@ void dcd_init(uint8_t rhport) LPC_USB->UDCAH = (uint32_t) _dcd.udca; LPC_USB->DMAIntEn = (DMA_INT_END_OF_XFER_MASK /*| DMA_INT_NEW_DD_REQUEST_MASK*/ | DMA_INT_ERROR_MASK); - sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect - - // USB IRQ priority should be set by application previously + // Clear pending IRQ NVIC_ClearPendingIRQ(USB_IRQn); } @@ -221,6 +219,18 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, SIE_DEV_STATUS_CONNECT_STATUS_MASK); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 0); +} + //--------------------------------------------------------------------+ // CONTROL HELPER //--------------------------------------------------------------------+ @@ -498,7 +508,7 @@ static void dd_complete_isr(uint8_t rhport, uint8_t ep_id) } // main USB IRQ handler -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { uint32_t const dev_int_status = LPC_USB->DevIntSt & LPC_USB->DevIntEn; LPC_USB->DevIntClr = dev_int_status;// Acknowledge handled interrupt diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 9af8e6019..c1f80185b 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -95,7 +95,7 @@ enum { CMDSTAT_DEVICE_ADDR_MASK = TU_BIT(7 )-1, CMDSTAT_DEVICE_ENABLE_MASK = TU_BIT(7 ), CMDSTAT_SETUP_RECEIVED_MASK = TU_BIT(8 ), - CMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), ///< reflect the softconnect only, does not reflect the actual attached state + CMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), ///< reflect the soft-connect only, does not reflect the actual attached state CMDSTAT_DEVICE_SUSPEND_MASK = TU_BIT(17), CMDSTAT_CONNECT_CHANGE_MASK = TU_BIT(24), CMDSTAT_SUSPEND_CHANGE_MASK = TU_BIT(25), @@ -209,6 +209,18 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + DCD_REGS->DEVCMDSTAT |= CMDSTAT_DEVICE_CONNECT_MASK; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + DCD_REGS->DEVCMDSTAT &= ~CMDSTAT_DEVICE_CONNECT_MASK; +} + //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ @@ -333,7 +345,7 @@ static void process_xfer_isr(uint32_t int_status) } } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; // TODO support multiple USB on supported mcu such as LPC55s69 diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 2872f1435..539629c3d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -322,7 +322,7 @@ void dcd_init(uint8_t rhport) { tu_memclr(&_dcd_data, sizeof(dcd_data_t)); - dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; // Reset controller dcd_reg->USBCMD |= USBCMD_RESET; @@ -342,7 +342,6 @@ void dcd_init(uint8_t rhport) dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/; dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0 - dcd_reg->USBCMD |= TU_BIT(0); // connect } void dcd_int_enable(uint8_t rhport) @@ -376,6 +375,18 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->USBCMD |= USBCMD_RUN_STOP; +} + +void dcd_disconnect(uint8_t rhport) +{ + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->USBCMD &= ~USBCMD_RUN_STOP; +} + //--------------------------------------------------------------------+ // HELPER //--------------------------------------------------------------------+ @@ -492,7 +503,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 320b7237e..7fd630384 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -201,6 +201,18 @@ void dcd_remote_wakeup(uint8_t rhport) DEV_WAKEUP(usbdev); } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + DEV_CONNECT(usbdev); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + DEV_DISCONNECT(usbdev); +} + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2939e5ae2..dbc1e6952 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -63,19 +63,16 @@ * Current driver limitations (i.e., a list of features for you to add): * - STALL handled, but not tested. * - Does it work? No clue. - * - All EP BTABLE buffers are created as max 64 bytes. - * - Smaller can be requested, but it has to be an even number. + * - All EP BTABLE buffers are created based on max packet size of first EP opened with that address. * - No isochronous endpoints * - Endpoint index is the ID of the endpoint * - This means that priority is given to endpoints with lower ID numbers * - Code is mixing up EP IX with EP ID. Everywhere. - * - No way to close endpoints; Can a device be reconfigured without a reset? * - Packet buffer memory is copied in the interrupt. * - This is better for performance, but means interrupts are disabled for longer * - DMA may be the best choice, but it could also be pushed to the USBD task. * - No double-buffering * - No DMA - * - No provision to control the D+ pull-up using GPIO on devices without an internal pull-up. * - Minimal error handling * - Perhaps error interrupts should be reported to the stack, or cause a device reset? * - Assumes a single USB peripheral; I think that no hardware has multiple so this is fine. @@ -131,15 +128,16 @@ * Configuration *****************************************************/ -// HW supports max of 8 endpoints, but this can be reduced to save RAM +// HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM +// (8u here would mean 8 IN and 8 OUT) #ifndef MAX_EP_COUNT -# define MAX_EP_COUNT 8u +# define MAX_EP_COUNT 8U #endif // If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it // Both of these MUST be a multiple of 2, and are in byte units. #ifndef DCD_STM32_BTABLE_BASE -# define DCD_STM32_BTABLE_BASE 0u +# define DCD_STM32_BTABLE_BASE 0U #endif #ifndef DCD_STM32_BTABLE_LENGTH @@ -163,7 +161,9 @@ typedef struct uint8_t * buffer; uint16_t total_len; uint16_t queued_len; - uint16_t max_packet_size; + uint16_t pma_ptr; + uint8_t max_packet_size; + uint8_t pma_alloc_size; } xfer_ctl_t; static xfer_ctl_t xfer_status[MAX_EP_COUNT][2]; @@ -177,15 +177,19 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; static uint8_t remoteWakeCountdown; // When wake is requested -// EP Buffers assigned from end of memory location, to minimize their chance of crashing // into the stack. -static uint16_t ep_buf_ptr; static void dcd_handle_bus_reset(void); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix); static void dcd_ep_ctr_handler(void); +// PMA allocation/access +static uint8_t open_ep_count; +static uint16_t ep_buf_ptr; ///< Points to first free memory location +static void dcd_pma_alloc_reset(void); +static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length); +static void dcd_pma_free(uint8_t ep_addr); +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); // Using a function due to better type checks // This seems better than having to do type casts everywhere else @@ -219,7 +223,7 @@ void dcd_init (uint8_t rhport) asm("NOP"); } USB->CNTR = 0; // Enable USB - + USB->BTABLE = DCD_STM32_BTABLE_BASE; reg16_clear_bits(&USB->ISTR, USB_ISTR_ALL_EVENTS); // Clear pending interrupts @@ -231,12 +235,6 @@ void dcd_init (uint8_t rhport) pcd_set_endpoint(USB,i,0u); } - // Initialize the BTABLE for EP0 at this point (though setting up the EP0R is unneeded) - // This is actually not necessary, but helps debugging to start with a blank RAM area - for(uint32_t i=0;i<(DCD_STM32_BTABLE_LENGTH>>1); i++) - { - pma[PMA_STRIDE*(DCD_STM32_BTABLE_BASE + i)] = 0u; - } USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); @@ -368,7 +366,7 @@ static void dcd_handle_bus_reset(void) pcd_set_endpoint(USB,i,0u); } - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) + dcd_pma_alloc_reset(); dcd_edpt_open (0, &ep0OUT_desc); dcd_edpt_open (0, &ep0IN_desc); @@ -501,7 +499,7 @@ static void dcd_ep_ctr_handler(void) } } -void dcd_irq_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) { (void) rhport; @@ -592,6 +590,85 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re } } +static void dcd_pma_alloc_reset(void) +{ + ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each) + //TU_LOG2("dcd_pma_alloc_reset()\r\n"); + for(uint32_t i=0; ipma_alloc_size = 0U; + xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_alloc_size = 0U; + xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_ptr = 0U; + xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_ptr = 0U; + } +} + +/*** + * Allocate a section of PMA + * + * If the EP number has already been allocated, and the new allocation + * is larger than the old allocation, then this will fail with a TU_ASSERT. + * (This is done to simplify the code. More complicated algorithms could be used) + * + * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. + */ +static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t* epXferCtl = xfer_ctl_ptr(epnum,dir); + + if(epXferCtl->pma_alloc_size != 0U) + { + //TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr); + // Previously allocated + TU_ASSERT(length <= epXferCtl->pma_alloc_size, 0xFFFF); // Verify no larger than previous alloc + return epXferCtl->pma_ptr; + } + + uint16_t addr = ep_buf_ptr; + ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer + + // Verify no overflow + TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF); + + epXferCtl->pma_ptr = addr; + epXferCtl->pma_alloc_size = length; + //TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr); + + return addr; +} + +/*** + * Free a block of PMA space + */ +static void dcd_pma_free(uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // Presently, this should never be called for EP0 IN/OUT + TU_ASSERT(open_ep_count > 2, /**/); + TU_ASSERT(xfer_ctl_ptr(epnum,dir)->max_packet_size != 0, /**/); + open_ep_count--; + + // If count is 2, only EP0 should be open, so allocations can be mostly reset. + + if(open_ep_count == 2) + { + ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT + 2*CFG_TUD_ENDPOINT0_SIZE; // 8 bytes per endpoint (two TX and two RX words, each), and EP0 + + // Skip EP0 + for(uint32_t i=1; ipma_alloc_size = 0U; + xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_alloc_size = 0U; + xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_ptr = 0U; + xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_ptr = 0U; + } + } +} + // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. @@ -601,28 +678,30 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); const uint16_t epMaxPktSize = p_endpoint_desc->wMaxPacketSize.size; + uint16_t pma_addr; + uint32_t wType; + // Isochronous not supported (yet), and some other driver assumptions. - TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); // Set type switch(p_endpoint_desc->bmAttributes.xfer) { case TUSB_XFER_CONTROL: - pcd_set_eptype(USB, epnum, USB_EP_CONTROL); + wType = USB_EP_CONTROL; break; #if (0) case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported - pcd_set_eptype(USB, epnum, USB_EP_ISOCHRONOUS); break; + wType = USB_EP_ISOCHRONOUS; break; #endif case TUSB_XFER_BULK: - pcd_set_eptype(USB, epnum, USB_EP_BULK); + wType = USB_EP_CONTROL; break; case TUSB_XFER_INTERRUPT: - pcd_set_eptype(USB, epnum, USB_EP_INTERRUPT); + wType = USB_EP_INTERRUPT; break; default: @@ -630,32 +709,59 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc return false; } + pcd_set_eptype(USB, epnum, wType); pcd_set_ep_address(USB, epnum, epnum); // Be normal, for now, instead of only accepting zero-byte packets (on control endpoint) // or being double-buffered (bulk endpoints) pcd_clear_ep_kind(USB,0); + pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); + if(dir == TUSB_DIR_IN) { - *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_tx_address_ptr(USB, epnum) = pma_addr; pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_tx_dtog(USB, epnum); pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK); } else { - *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_rx_address_ptr(USB, epnum) = pma_addr; pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_rx_dtog(USB, epnum); pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK); } xfer_ctl_ptr(epnum, dir)->max_packet_size = epMaxPktSize; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + p_endpoint_desc->wMaxPacketSize.size); // increment buffer pointer return true; } +/** + * Close an endpoint. + * + * This function may be called with interrupts enabled or disabled. + * + * This also clears transfers in progress, should there be any. + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + uint32_t const epnum = tu_edpt_number(ep_addr); + uint32_t const dir = tu_edpt_dir(ep_addr); + + if(dir == TUSB_DIR_IN) + { + pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); + } + else + { + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); + } + + dcd_pma_free(ep_addr); +} + // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index dc752b37a..0c9c2650d 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -209,10 +209,6 @@ void dcd_init (uint8_t rhport) // Enable USB transceiver. USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; - - // Soft Connect -> Enable pullup on D+/D-. - // This step does not appear to be specified in the programmer's model. - dev->DCTL &= ~USB_OTG_DCTL_SDIS; } void dcd_int_enable (uint8_t rhport) @@ -250,6 +246,23 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + + dev->DCTL &= ~USB_OTG_DCTL_SDIS; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + + dev->DCTL |= USB_OTG_DCTL_SDIS; +} + + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ @@ -656,7 +669,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType } } -void dcd_irq_handler(uint8_t rhport) { +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index d29c98e55..ba1383f31 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -91,6 +91,18 @@ void dcd_remote_wakeup (uint8_t rhport) (void) rhport; } +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; +} + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index edccec33f..da75a7f3f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -134,9 +134,6 @@ void dcd_init (uint8_t rhport) // Enable reset and wait for it before continuing. USBIE |= RSTRIE; - // Enable pullup. - USBCNF |= PUR_EN; - USBKEYPID = 0; } @@ -207,6 +204,28 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + dcd_int_disable(rhport); + + USBKEYPID = USBKEY; + USBCNF |= PUR_EN; // Enable pullup. + USBKEYPID = 0; + + dcd_int_enable(rhport); +} + +void dcd_disconnect(uint8_t rhport) +{ + dcd_int_disable(rhport); + + USBKEYPID = USBKEY; + USBCNF &= ~PUR_EN; // Disable pullup. + USBKEYPID = 0; + + dcd_int_enable(rhport); +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ @@ -539,7 +558,7 @@ static void handle_setup_packet(void) dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void) rhport; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 1054e71d6..8dde874fc 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -397,6 +397,19 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + usb_pullup_out_write(1); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + usb_pullup_out_write(0); +} + + //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ @@ -613,7 +626,7 @@ static void handle_setup(void) usb_setup_ev_pending_write(1); } -void dcd_irq_handler(uint8_t rhport) +void dcd_int_handler(uint8_t rhport) { (void)rhport; uint8_t next_ev; diff --git a/src/tusb_option.h b/src/tusb_option.h index 6e2a2f125..0826a5aab 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -124,15 +124,6 @@ #define OPT_MODE_HIGH_SPEED 0x10 ///< High speed /** @} */ -/** \defgroup group_supported_netif Supported Network Interface - * \ref CFG_TUD_NET must be defined to one of these - * @{ */ -#define OPT_NET_NONE 0 ///< No network interface -#define OPT_NET_ECM 1 ///< CDC-ECM -#define OPT_NET_RNDIS 2 ///< RNDIS -#define OPT_NET_EEM 3 ///< CDC-EEM -/** @} */ - #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif